Django通过签名网址上传到Amazon S3:内容类型错误

时间:2015-08-22 17:12:52

标签: django amazon-s3 boto

在我的Django应用程序(使用DjangoRestFramwework的RESTful API)中,我必须在Amazon S3上存储图像。由于某些技术限制,我们必须使用签名URL通过客户端应用程序直接上传。一切正常但在客户端执行上传后,内容类型始终设置为binary/octet-stream,而我自然希望它是,image/jpeg。正如在Amazon S3文档here中提到的那样,必须将response-content-type标头添加到签名URL中,以确保S3的响应的Content-Type是正确的。这是我签署URL的代码(根据boto文档编写):

connection = S3Connection(
    aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
    aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY
)    
url = connection.generate_url(
    100,
    'PUT',
    settings.AWS_STORAGE_BUCKET_NAME,
    some_key,
    response_headers={'response-content-type':'image/jpeg'},
)

此代码几乎可以正常工作:它会生成一个我成功用于上传的URL。 curl请求是:

curl -v --request PUT --upload-file ~/file.jpg --header "response-content-type : image/jpeg" "https://mybucket.s3.amazonaws.com/file.jpg?Signature=ytmFHV13qeVg1aU6xyTuysOG4Bs%3D&Expires=1440263232&AWSAccessKeyId=XXXXXXXXXXXXXXXX&response-content-type=image/jpeg"

不幸的是,当我访问该文件时,内容类型仍然是错误的(binary/octet-stream)。我做错了吗?

1 个答案:

答案 0 :(得分:3)

今天,经过大量实验,我找到了答案。我的灵感来自... official Amazon S3 documentation :)以下是URL签名代码:

/

此处的主要更改是标题部分,我放置了<div class="cm-notification-content cm-notification-content-extended notification-content-extended cm-auto-hide" data-ca-notification-key="3b71ec814b1cb78f78b7b6602c6258a6" style="top: 143.5px;"><h1>Congrats. You've just added to Cart ...<span class="cm-notification-close close"></span></h1><div class="notification-body-extended"><div class="ty-product-notification__body cm-notification-max-height" style="max-height: 367px;"> <div class="ty-product-notification__item clearfix"> <img class="ty-pict ty-product-notification__image " src="http://aus2015.ambientlounge.com/images/thumbnails/100/100/detailed/2/wildberry.jpg?t=1440337739" alt="" title=""> <div class="ty-product-notification__content clearfix butterfly-sofa-bean-bags"> <a href="http://aus2015.ambientlounge.com/interior/gold-class-bean-bags/acoustic-sofa-bean-bags/wildberry-deluxe.html" class="ty-product-notification__product-name">Wildberry Deluxe</a> <div class="ty-product-notification__price"> <span class="none">1</span>&nbsp;x&nbsp;<span class="none">$</span><span id="sec_price_2343099257" class="none">269.00</span> </div> </div> </div> <form action="search_postcode.php" method="post" class="postcode_locator_form" name="postcode_locator_form"> <div class="ty-control-group"> <label for="postcode_locator_search" class="ty-control-group__title">Check we can send you filling (metro only)</label> <div class="ty-input-append ty-m-none"> <input type="text" size="20" class="ty-input-text" id="postcode_locator_search" name="postcode_locator_search" value="" placeholder="Enter postcode"> <button title="Search" class="ty-btn-go" type="submit">Go!</button> <input type="hidden" name="dispatch" value="postcode_locator.search"> </div> </div> </form> <div class="filling-status filling-success" style="display: none;"> <h3>Add filling to your bean bag</h3> <hr> <p>Searched postcode: <span class="searched-postcode"></span></p> <p class="beans-msg alert alert-success">Congratulations! we are able to deliver beans to your postcode! To add filling to your bean bag just <a href="http://aus2015.ambientlounge.com/index.php?dispatch=checkout.add_bean_bag_filling&amp;product_id=727">click here</a></p> </div> <div class="filling-status filling-failure" style="display: none;"> <h3>Add filling to your bean bag</h3> <hr> <p>Searched postcode: <span class="searched-postcode"></span></p> <p class="beans-msg alert alert-error">Unfortunately we cannot delivery filling to your postcode, your item has already been added to your Cart but you will receive the cover only.</p> </div> <script> $(function() { $(".filling-status").hide(); $(".postcode_locator_form .ty-btn-go").click(function() { // getting the value that user typed var searchString = $("#postcode_locator_search").val(); // forming the queryString var data = 'postcode_locator_search='+ searchString; // if searchString is not empty if(searchString) { // ajax call $.ajax({ type: "POST", url: "search_postcode.php", data: data, beforeSend: function(data) { // this happens before actual call $(".searched-postcode").html(searchString); }, success: function(data){ // this happens after we get results console.log(data); if(data == '0'){ $(".filling-status.filling-failure").hide(); $(".filling-status.filling-success").show(); } else if(data == '1'){ $(".filling-status.filling-success").hide(); $(".filling-status.filling-failure").show(); } } }); } return false; }); }); </script> <div class="clearfix"></div> <hr class="ty-product-notification__divider"> <div class="ty-product-notification__total-info clearfix"> <div class="ty-product-notification__amount ty-float-left"> You now have 35 items in your cart</div> <div class="ty-product-notification__subtotal ty-float-right"> Cart subtotal $<span>7,337.85</span> </div> </div> </div><div class="ty-product-notification__buttons clearfix"> <div class="ty-float-left"> <a href="http://aus2015.ambientlounge.com/index.php?dispatch=checkout.cart" class="ty-btn ty-btn__secondary ">View my Cart</a> </div> <div class="ty-float-right"> <a href="http://aus2015.ambientlounge.com/index.php?dispatch=checkout.checkout" class="ty-btn ty-btn__primary ">Pay Now</a> </div> </div></div></div> url = connection.generate_url( 100, 'PUT', settings.AWS_STORAGE_BUCKET_NAME, some_key, headers = {'x-amz-acl' : 'public-read', 'Content-Type': 'image/jpeg'} ) 也很有用,因为它使您的文件可以公开阅读)。然后,您必须将'Content-Type': 'image/jpeg'标头放入HTTP请求中。就我而言,我使用'x-amz-acl' : 'public-read'如下:

Content-Type

享受!