2014-04-16 6 views
5

Ich habe Probleme beim Löschen einer Datei aus S3 mit Fineuploader und Django/boto. Ich bin in der Lage, Dateien erfolgreich mit Fineuploader zu S3 zu laden, und die Bildurl abzurufen und anzuzeigen, aber das Löschen war nicht erfolgreich.Löschen einer Datei aus S3 mit Django + Fineuploader + boto

Aus dem Blick auf die Boto-Debug-Protokolle sieht es so aus, als ob Boto das Token nicht als Teil der Anfrage an S3 sendet und ich denke, das könnte mein Problem sein.

Zuerst habe ich die boto Debug-Ausgabe, weil ich jemand mehr mit ihm vertraut vermuten, nach einem Blick auf sie helfen kann, aber ich habe meine volle Setup danach (was das Beispiel bei https://github.com/Widen/fine-uploader-server/blob/master/python/django-fine-uploader-s3/ so eng wie möglich folgt)

Terminal-Ausgabe auf Lösch

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 

Offensichtlich habe ich meinen tatsächlichen Bucket-Namen dort, wie gesagt Uploading funktioniert, so glaube ich nicht, dass das Problem in den Einstellungen ist.

Fineuploader Instanz

$("#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()) 
    } 
+0

Hmm ... Ich bin nicht in der Lage, dies zu reproduzieren. Was ist die Ausgabe von 'pip freeze'? Und gibt es Stack-Traces oder andere nützliche Log-Nachrichten im Terminal? –

+0

Der 500-Fehler in der letzten Zeile Ihres Terminalprotokolls weist darauf hin, dass beim Django-Server ein Fehler aufgetreten ist. Ist das dein _entire_ 'views.py'? –

+0

Das ist nicht die gesamte views.py, aber es ist der einzige Teil, der fineuploader beinhaltet. Nachdem Sie erwähnt haben, dass es etwas auf dem Django-Server ist, bemerkte ich, dass es die 'handle_delete'-Ansicht erreicht, die 'if boto'-Bedingungen erfüllt und dann' make_response (200) 'aufrufen sollte. Beim Aufruf 'aws_key.delete()' scheint etwas schiefzugehen. – berserkia

Antwort

2

Es stellte sich heraus, dass ich hatte meine S3-Bucket-Richtlinie nicht korrekt konfiguriert, um auch DELETE-Anfragen von meinem Server zuzulassen, daher zeigten die Bucket-Logs einen Fehler 204. Ich hatte PUT- und GET-Requests zugelassen, daher funktionierte das Hoch- und Herunterladen, aber nicht DELETE. Ich habe meine Bucket-Richtlinie geändert:

{ 
    "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/*" 
    } 
    ] 
}