在我的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
)。我做错了吗?
答案 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> x <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&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
享受!