在浏览器中将PUT上传到S3时忽略内容类型?

时间:2015-04-22 04:59:42

标签: python django heroku amazon-s3

在我的django项目中(几乎)成功地从浏览器设置了s3上传,我遇到了一个我似乎无法弄清楚的最后一个障碍。在创建签名以将内容上传到s3时,似乎没有任何方法可以忽略设置内容类型。

删除内容类型会有所帮助的原因是,在safari和chrome中,一些带有uppopular扩展名的文件(甚至.zip不会工作)会给我一个"请求签名我们计算结果与您提供的签名不符。检查您的密钥和签名方法"由于浏览器无法识别我认为的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')

1 个答案:

答案 0 :(得分:1)

基本上这个问题可以归结为这样一个事实:在指南提供的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脚本。从那里我刚刚修改了脚本,在执行put时使用我的mime_type作为内容类型头,而不是它一直在做什么(使用file.type)