- 背景
項目裏有圖片上傳的需求,具體實現是後端生成presigned url(預簽名url,裏面包含上傳到AWS S3所需要的一些認證標識信息)給到前端,前端通過這個URL將文件上傳到雲服務上。但是上傳成功後,從CDN上下載下來的文件打不開,而且只有前端有這個問題,客戶端可以正常上傳,一開始以爲是框架問題,而且亞馬遜官方也沒有直接上傳相關的文檔(都是使用SDK的方式上傳),所以問題很難定位,後來在github上找到了方案。 - 相關步驟
- 從後端獲取presigned url ,亞馬遜官網有Java、PHP、node等生成presigned url的文檔
- 使用presigned url上傳圖片,前端使用的是element UI + axios, 這裏使用的element UI 自定義上傳的方式,特別需要注意的就是直接上傳文件,不要用formdata的格式上傳
HTML部分
<el-upload
class="avatar-uploader"
action="123"
:http-request="upload"
:before-upload="beforeAvatarUpload">
<img v-if="params.defaultImgUrl" :src="params.defaultImgUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
js 部分
upload(res)
{
let file = res.file; //注意:直接上傳file文件,不要用FormData對象的形式傳
let config = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
//從接口獲取presigned url
getUploadUrl({uploadType: 6}).then(res => {
let result = res.data;
if (result.code === 0) {
const info = JSON.parse(result.msg);
//需要用put方法上傳,post會報405,aws官方規定是put方法
axios.put(info.presignedUrl, file, config)
.then(res => {
if (res.status == 200) {
this.params.defaultImgUrl = info.cdnUrl;
}
}).catch(
err => {
console.log(err)
}
)
}
}).catch(err => {
console.log('get upload info', err)
})
}
- 返回200狀態碼即表示上傳成功
- 坑點
一般圖片、文件上傳都是使用FormData對象傳遞二進制文件,所以筆者一開始也是採用的這種方式上傳到AWS上,但是上傳完之後,下載後的圖片無法打開,將其二進制數據與原文件二級制數進行對比,發現有額外的二進制數據
後來在github上找到了解決方案,原來使FormData對象上傳文件到aws上會損壞原文件的二進制數據,直接上傳文件對象就行
附上參考的解決方案github地址:
https://github.com/aws/aws-sdk-js/issues/547