【问题标题】:Deleting a file from S3 using Django + Fineuploader + boto使用 Django + Fineuploader + boto 从 S3 中删除文件
【发布时间】:2014-05-31 23:04:03
【问题描述】:

我在使用 Fineuploader 和 Django/boto 从 S3 删除文件时遇到问题。我能够使用 Fineuploader 成功将文件上传到 S3,并检索并显示图像 url,但删除不成功。

通过查看 boto 调试日志,boto 似乎没有将令牌作为请求的一部分发送到 S3,我认为这可能是我的问题。

首先我有 boto 调试输出,因为我怀疑更熟悉它的人在查看它之后会提供帮助,但之后我有完整的设置(尽可能接近 https://github.com/Widen/fine-uploader-server/blob/master/python/django-fine-uploader-s3/ 的示例)

删除时的终端输出

bucket_name:  XXXXXXXX
key_name: b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg
aws_bucket:  <Bucket: XXXXXXXXX>
aws_key:  <Key: XXXXXXXX,b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg>
2014-04-17 15:01:56,576 boto [DEBUG]:path=/b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg
2014-04-17 15:01:56,577 boto [DEBUG]:auth_path=/thisorthis/b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg
2014-04-17 15:01:56,577 boto [DEBUG]:Method: DELETE
2014-04-17 15:01:56,577 boto [DEBUG]:Path: /b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg
2014-04-17 15:01:56,577 boto [DEBUG]:Data:
2014-04-17 15:01:56,577 boto [DEBUG]:Headers: {}
2014-04-17 15:01:56,577 boto [DEBUG]:Host: XXXXXXX.s3.amazonaws.com
2014-04-17 15:01:56,578 boto [DEBUG]:Port: 443
2014-04-17 15:01:56,578 boto [DEBUG]:Params: {}
2014-04-17 15:01:56,578 boto [DEBUG]:establishing HTTPS connection: host=thisorthis.s3.amazonaws.com, kwargs={'port': 443, 'timeout': 70}
2014-04-17 15:01:56,578 boto [DEBUG]:Token: None
2014-04-17 15:01:56,578 boto [DEBUG]:StringToSign:
DELETE


Thu, 17 Apr 2014 15:01:56 GMT
/XXXXXXXX/b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg
2014-04-17 15:01:56,579 boto [DEBUG]:Signature:
AWS AKIAJYS27FQSNHPH3CXQ:dVKlBpulsY9LrOtHOa+xQmurIEM=
[17/Apr/2014 15:01:57] "DELETE /s3/delete/b45069b8-dc44-45fe-8b67-b25fc088bdea?key=b45069b8-dc44-45fe-8b67-b25fc088bdea.jpg&bucket=XXXXXXXX HTTP/1.1" 500 15975

settings.py:

AWS_CLIENT_SECRET_KEY = os.getenv("AWS_CLIENT_SECRET_KEY") 
AWS_SERVER_PUBLIC_KEY = os.getenv("AWS_SERVER_PUBLIC_KEY")
AWS_SERVER_SECRET_KEY = os.getenv("AWS_SERVER_SECRET_KEY")

AWS_EXPECTED_BUCKET = 'mybucketname'
AWS_MAX_SIZE = 15000000

显然我在那里有我的实​​际存储桶名称,正如我所说的上传工作正常,所以我认为问题不在设置中。

Fineuploader 实例

  $("#fine-uploader).fineUploaderS3({
        debug: true,
        request: {
            endpoint: 'XXXXX',
            accessKey: 'XXXXXXXX'
        },

        template: "simple-previews-template",

        signature: {
            endpoint: '/s3/signature/'
        },
        uploadSuccess: {
            endpoint: '/s3/success/'
        },

        iframeSupport: {
            localBlankPagePath: '/success.html'
        },

        deleteFile: {
            enabled: true,
            endpoint: '/s3/delete/'
        },

        classes: {
           dropActive: "cssClassToAddToDropZoneOnEnter"
        },

    }) 

urls.py

url(r'^s3/signature/', views.handle_s3, name="s3_signee"),
url(r'^s3/delete/', views.handle_s3, name='s3_delete'),
url(r'^s3/success/', views.success_redirect_endpoint, name="s3_succes_endpoint")

views.py

try:
    import boto
    from boto.s3.connection import Key, S3Connection
    boto.set_stream_logger('boto')
    S3 = S3Connection(development.AWS_SERVER_PUBLIC_KEY, development.AWS_SERVER_SECRET_KEY)
except ImportError, e:
    print("Could not import boto, the Amazon SDK for Python.")
    print("Deleting files will not work.")
    print("Install boto with")
    print("$ pip install boto")



@csrf_exempt
def success_redirect_endpoint(request):
    """ This is where the upload will snd a POST request after the 
    file has been stored in S3.
    """

    key = request.POST.get('key')
    response = {}
    response['url'] = key
    return HttpResponse(json.dumps(response), content_type="application/json")


@csrf_exempt
def handle_s3(request):
    """ View which handles all POST and DELETE requests sent by Fine Uploader
    S3. You will need to adjust these paths/conditions based on your setup.
    """

    if request.method == "POST":
        return handle_POST(request)
    elif request.method == "DELETE":
        return handle_DELETE(request)
    else:
        return HttpResponse(status=405)

def handle_POST(request):
    """ Handle S3 uploader POST requests here. For files <=5MiB this is a simple
    request to sign the policy document. For files >5MiB this is a request
    to sign the headers to start a multipart encoded request.
    """

    if request.POST.get('success', None):
        return make_response(200)
    else:
        request_payload = json.loads(request.body)
        headers = request_payload.get('headers', None)

        if headers:
            print "headers"
            # The presence of the 'headers' property in the request payload 
            # means this is a request to sign a REST/multipart request 
            # and NOT a policy document
            response_data = sign_headers(headers)
        else:
            print "no headers"
            if not is_valid_policy(request_payload):
                print "is not valid"
                return make_response(400, {'invalid': True})

            response_data = sign_policy_document(request_payload)
        response_payload = json.dumps(response_data)
        return make_response(200, response_payload)

def handle_DELETE(request):
    """ Handle file deletion requests. For this, we use the Amazon Python SDK,
    boto.
    """
    print "handle delete"
    if boto:
        bucket_name = request.REQUEST.get('bucket')
        print "bucket_name: ", bucket_name
        key_name = request.REQUEST.get('key')
        print "key_name:", key_name
        aws_bucket = S3.get_bucket(bucket_name, validate=False)
        print "aws_bucket: ", aws_bucket
        aws_key = Key(aws_bucket, key_name)
        print "aws_key: ", aws_key
        aws_key.delete()
        print "after aws_key.delete()"
        return make_response(200)
    else:
        return make_response(500)

def make_response(status=200, content=None):
    """ Construct an HTTP response. Fine Uploader expects 'application/json'.
    """

    response = HttpResponse()
    response.status_code = status
    response['Content-Type'] = "application/json"
    response.content = content
    return response

def is_valid_policy(policy_document):
    """ Verify the policy document has not been tampered with client-side
    before sending it off. 
    """
    bucket = development.AWS_EXPECTED_BUCKET
    parsed_max_size = development.AWS_MAX_SIZE
    print "check validity"

    # bucket = ''
    # parsed_max_size = 0


    for condition in policy_document['conditions']:
        if isinstance(condition, list) and condition[0] == 'content-length-range':
            parsed_max_size = condition[2]
        else:
            if condition.get('bucket', None):
                bucket = condition['bucket']

    return bucket == development.AWS_EXPECTED_BUCKET and parsed_max_size == development.AWS_MAX_SIZE

def sign_policy_document(policy_document):
    """ Sign and return the policy doucument for a simple upload.
    http://aws.amazon.com/articles/1434/#signyours3postform
    """
    policy = base64.b64encode(json.dumps(policy_document))
    signature = base64.b64encode(hmac.new(development.AWS_CLIENT_SECRET_KEY, policy, hashlib.sha1).digest())
    return {
        'policy': policy,
        'signature': signature
    }

def sign_headers(headers):
    """ Sign and return the headers for a chunked upload. """
    print "sign headers"
    return {
        'signature': base64.b64encode(hmac.new(development.AWS_CLIENT_SECRET_KEY, headers, hashlib.sha1).digest())
    }

【问题讨论】:

  • 嗯...我无法重现这个。 pip freeze 的输出是什么?终端中是否有任何堆栈跟踪或其他有用的日志消息?
  • 终端日志最后一行中的 500 错误表明 Django 服务器出现问题。那是你的整个views.py吗?
  • 这不是views.py的全部,但它是唯一涉及fineuploader的部分。在你提到它在 Django 服务器上之后,我注意到它到达了handle_delete 视图,满足if boto 条件,然后应该调用make_response(200)aws_key.delete() 通话似乎出了点问题。
  • 在阅读了DELETE Bucket Policy 之后,我认为我的存储桶策略配置不正确...
  • 不错!如果是这种情况,您应该将其设置为答案。另外,如果这是真的,我可以考虑在 django 服务器的 delete 方法中添加一个 try/catch,以便为将来可能遇到此问题的任何人提供线索。

标签: python django amazon-s3 boto fine-uploader


【解决方案1】:

原来我没有正确配置我的 S3 存储桶策略也允许来自我的服务器的 DELETE 请求,因此存储桶日志显示错误 204。我允许 PUT 和 GET 请求,因此上传和检索工作,但没有删除。我将存储桶策略更改为更像:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListAllMyBuckets"],
      "Resource": "arn:aws:s3:::*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": "arn:aws:s3:::xxxxx"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::xxxxx/*"
    }
  ]
}

【讨论】:

    猜你喜欢
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 2017-08-18
    • 1970-01-01
    • 2013-12-29
    • 2015-06-05
    相关资源
    最近更新 更多