python - Deleting a file from S3 using Django + Fineuploader + boto -
i having trouble deleting file s3 using fineuploader , django/boto. able upload files s3 fineuploader, , retrieve , display image url, deleting hasn't been successful.
from looking @ boto debug logs, looks boto not sending token part of request s3 , think may problem.
first have boto debug output because suspect more familiar can after looking @ it, have full setup afterwards (which follows example @ https://github.com/widen/fine-uploader-server/blob/master/python/django-fine-uploader-s3/ closely possible)
terminal output on delete
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 obviously have actual bucket name there, said uploading working don't think issue in settings.
fineuploader instance
$("#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 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, amazon sdk python.") print("deleting files not work.") print("install boto with") print("$ pip install boto") @csrf_exempt def success_redirect_endpoint(request): """ upload snd post request after 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 handles post , delete requests sent fine uploader s3. need adjust these paths/conditions based on 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. files <=5mib simple request sign policy document. files >5mib request sign headers start 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" # presence of 'headers' property in request payload # means request sign rest/multipart request # , not 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. this, use 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 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 policy document has not been tampered client-side before sending off. """ bucket = development.aws_expected_bucket parsed_max_size = development.aws_max_size print "check validity" # bucket = '' # parsed_max_size = 0 condition in policy_document['conditions']: if isinstance(condition, list) , 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 , parsed_max_size == development.aws_max_size def sign_policy_document(policy_document): """ sign , return policy doucument 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 , return headers chunked upload. """ print "sign headers" return { 'signature': base64.b64encode(hmac.new(development.aws_client_secret_key, headers, hashlib.sha1).digest()) }
it turned out had not configured s3 bucket policy allow delete requests server, hence bucket logs showing error 204. had allowed put , requests, hence uploading , retrieval worked, not delete. changed bucket policy more like:
{ "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/*" } ] }
Comments
Post a Comment