在浏览器中将 PUT 上传到 S3 时忽略内容类型?
Ignoring content-type when doing PUT upload to S3 in browser?
在我的 django 项目上(几乎)成功地从浏览器设置了 s3 上传,我 运行 遇到了最后一个我似乎无法弄清楚的障碍。在创建签名以将内容上传到 s3 时,似乎没有任何方法可以忽略设置内容类型。
删除内容类型会有帮助的原因是,在 safari 和 chrome 中,一些具有流行扩展名的文件(即使 .zip 也不起作用)会给我一个 "The request signature we calculated does not match the signature you provided. Check your key and signing method" 由于浏览器无法识别我认为的 mime 类型(至少每当我打印出来并且出现错误时,它是空白的)。
这是我遵循的指南:https://devcenter.heroku.com/articles/s3-upload-python,除了无法确定 MIME 类型时,它运行良好。这也是我稍微修改过的代码的副本:
import base64
from hashlib import sha1
import hmac
AWS_ACCESS_KEY = 'X'
AWS_SECRET_KEY = 'XX'
S3_BUCKET = 'XX/X/X'
object_name = urllib.quote_plus(request.GET['s3_object_name'])
print "object_name: ", object_name.lower()
mime_type = request.GET['s3_object_type']
#on some files this is blank and thats the ones that give me 403 errors from s3
print "mime Type: ", mime_type
expires = int(time.time()+15)
amz_headers = "x-amz-acl:public-read"
# Generate the PUT request that JavaScript will use:
put_request = "PUT\n\n%s\n%d\n%s\n/%s/%s" % (mime_type, expires, amz_headers, S3_BUCKET, object_name)
# Generate the signature with which the request can be signed:
signature = base64.encodestring(hmac.new(AWS_SECRET_KEY, put_request, sha1).digest())
# Remove surrounding whitespace and quote special characters:
signature = urllib.quote_plus(signature.strip())
# Build the URL of the file in anticipation of its imminent upload:
url = 'https://%s.s3.amazonaws.com/media/attachments/%s' % ('S3_BUCKET', object_name)
content = json.dumps({
'signed_request': '%s?AWSAccessKeyId=%s&Expires=%d&Signature=%s' % (url, AWS_ACCESS_KEY, expires, signature),
'url': url
})
print content
# Return the signed request and the anticipated URL back to the browser in JSON format:
return HttpResponse(content, mimetype='text/plain; charset=x-user-defined')
基本上这个问题可以归因于指南提供的 s3_upload.js 中,阅读 file.type 不正确所以我修改了这部分代码
object_name = urllib.quote_plus(request.GET['s3_object_name'])
print "object_name: ", object_name.lower()
mime_type = request.GET['s3_object_type']
#on some files this is blank and thats the ones that give me 403 errors from s3
print "mime Type: ", mime_type
到
mime_type = request.GET['s3_object_type']
print "mime Type: ", mime_type
mtype,encoding = mimetypes.guess_type(object_name)
print "guessed mime type", mtype
mime_type = mtype
然后将内容更改为
content = json.dumps({
'signed_request': '%s?AWSAccessKeyId=%s&Expires=%d&Signature=%s' % (url, AWS_ACCESS_KEY, expires, signature),
'url': url,
'mime_type' : mime_type
})
将其传递回 javascript 脚本。从那里我只是修改了脚本以在执行放置时使用我的 mime_type 作为 content-type header,而不是它一直在做的事情(使用 file.type)
在我的 django 项目上(几乎)成功地从浏览器设置了 s3 上传,我 运行 遇到了最后一个我似乎无法弄清楚的障碍。在创建签名以将内容上传到 s3 时,似乎没有任何方法可以忽略设置内容类型。
删除内容类型会有帮助的原因是,在 safari 和 chrome 中,一些具有流行扩展名的文件(即使 .zip 也不起作用)会给我一个 "The request signature we calculated does not match the signature you provided. Check your key and signing method" 由于浏览器无法识别我认为的 mime 类型(至少每当我打印出来并且出现错误时,它是空白的)。
这是我遵循的指南:https://devcenter.heroku.com/articles/s3-upload-python,除了无法确定 MIME 类型时,它运行良好。这也是我稍微修改过的代码的副本:
import base64
from hashlib import sha1
import hmac
AWS_ACCESS_KEY = 'X'
AWS_SECRET_KEY = 'XX'
S3_BUCKET = 'XX/X/X'
object_name = urllib.quote_plus(request.GET['s3_object_name'])
print "object_name: ", object_name.lower()
mime_type = request.GET['s3_object_type']
#on some files this is blank and thats the ones that give me 403 errors from s3
print "mime Type: ", mime_type
expires = int(time.time()+15)
amz_headers = "x-amz-acl:public-read"
# Generate the PUT request that JavaScript will use:
put_request = "PUT\n\n%s\n%d\n%s\n/%s/%s" % (mime_type, expires, amz_headers, S3_BUCKET, object_name)
# Generate the signature with which the request can be signed:
signature = base64.encodestring(hmac.new(AWS_SECRET_KEY, put_request, sha1).digest())
# Remove surrounding whitespace and quote special characters:
signature = urllib.quote_plus(signature.strip())
# Build the URL of the file in anticipation of its imminent upload:
url = 'https://%s.s3.amazonaws.com/media/attachments/%s' % ('S3_BUCKET', object_name)
content = json.dumps({
'signed_request': '%s?AWSAccessKeyId=%s&Expires=%d&Signature=%s' % (url, AWS_ACCESS_KEY, expires, signature),
'url': url
})
print content
# Return the signed request and the anticipated URL back to the browser in JSON format:
return HttpResponse(content, mimetype='text/plain; charset=x-user-defined')
基本上这个问题可以归因于指南提供的 s3_upload.js 中,阅读 file.type 不正确所以我修改了这部分代码
object_name = urllib.quote_plus(request.GET['s3_object_name'])
print "object_name: ", object_name.lower()
mime_type = request.GET['s3_object_type']
#on some files this is blank and thats the ones that give me 403 errors from s3
print "mime Type: ", mime_type
到
mime_type = request.GET['s3_object_type']
print "mime Type: ", mime_type
mtype,encoding = mimetypes.guess_type(object_name)
print "guessed mime type", mtype
mime_type = mtype
然后将内容更改为
content = json.dumps({
'signed_request': '%s?AWSAccessKeyId=%s&Expires=%d&Signature=%s' % (url, AWS_ACCESS_KEY, expires, signature),
'url': url,
'mime_type' : mime_type
})
将其传递回 javascript 脚本。从那里我只是修改了脚本以在执行放置时使用我的 mime_type 作为 content-type header,而不是它一直在做的事情(使用 file.type)