每一個OSS的用戶都會用到上傳服務。Web端常見的上傳方法是用戶在瀏覽器或app端上傳文件到應用服務器,而後應用服務器再把文件上傳到OSS。html
和數據直傳到OSS相比,以上方法有三個缺點:前端
Web端直傳共有三種方式:ios
在客戶端經過JavaScript代碼完成簽名,無需過多配置,便可實現直傳,很是方便。可是客戶端經過JavaScript把AccesssKeyID 和AccessKeySecret寫在代碼裏面有泄露的風險。web
web端向服務端請求籤名,而後直接上傳,不會對服務端產生壓力,並且安全可靠。然而有個問題,就是用戶上傳了多少文件,上傳了什麼文件,服務端並不能立刻知道,若是想實時瞭解用戶上傳了什麼文件,能夠採用第三種方式。json
本文將演示如何經過第三種方式完成文件直傳到OSS服務器。axios
window.onload = function () { let upload = document.getElementById("upload") let link = document.getElementById("link") let obj = {} // 獲取簽名地址 // const url = "http://gt-activity.gtdreamlife.com/api/oss/ossSign" axios.get(url).then(res => { if (res.data.statusCode === 200) { // 下面是簽名直傳服務返回給客戶端的消息body內容的示例,這個body的內容將做爲客戶端上傳文件的重要參數。 let { dirPath, key, host, policy, Signature, callback, OSSAccessKeyId } = res.data.result obj.host = host obj.key = dirPath + key + "${filename}" obj.policy = policy obj.Signature = Signature obj.callback = callback obj.OSSAccessKeyId = OSSAccessKeyId console.log(obj) } else { alert(res.data.message) } }) document.querySelector("#file").onchange = function (e) { let data = e.target.files[0] console.log(data) let formData = new FormData() for (let key in obj) { formData.append(key, obj[key]) } // append 文件必須放在最後,否則會報key錯誤 formData.append("file", data) axios.post(obj.host, formData).then(res => { const result = res.data document.querySelector("#link").value = result.data }) } }
阿里雲OSS配置信息api
const config = { dirPath: 'oss/file/', // oss 文件夾 不存在會自動建立 bucket: '${bucket}', // oss應用名 region: '${region}', // oss節點名 accessKeyId: '${accessKeyId}', // 申請的osskey accessKeySecret: '${accessKeySecret}', // 申請的osssecret callbackPath: 'api/oss/ossCallback', // 回調接口 expAfter: 6000, // 簽名失效時間 maxSize: 1048576000, // 最大文件大小 };
獲取簽名接口
服務器返回數據Callback API瀏覽器
// 圖片簽名 async ossSign() { const { bucket, region, expAfter, maxSize, dirPath, accessKeyId, accessKeySecret, callbackPath, } = config; const host = `https://${bucket}.${region}.aliyuncs.com`; // 你的oss完整地址 // 回調接口的主機和端口 const { callbackHost, callbackPort } = this.app.config.oss; const expireTime = new Date().getTime() + expAfter; const expiration = new Date(expireTime).toISOString(); const policyString = JSON.stringify({ expiration, conditions: [ [ 'content-length-range', 0, maxSize ], [ 'starts-with', '$key', dirPath ], ], }); const policy = Buffer(policyString).toString('base64'); // 建立簽名 const Signature = crypto.createHmac('sha1', accessKeySecret).update(policy).digest('base64'); const callbackBody = { // callbackUrl爲 上傳回調服務器的URL,請將下面的IP和Port配置爲您本身的真實信息。 callbackUrl: `https://${callbackHost}${callbackPort ? `:${callbackPort}` : ''}/${callbackPath}`, callbackHost: `${callbackHost}`, // 規定返回數據的格式,當前默認返回圖片信息、寬度、高度,可獲取更多數據。參考上方連接 callbackBody: '{"filename": ${object},"size": ${size},"width": ${imageInfo.width},"height": ${imageInfo.height}}', callbackBodyType: 'application/json', }; const callback = Buffer(JSON.stringify(callbackBody)).toString('base64'); this.ctx.body = ({ statusCode: 200, message: 'oss簽名成功', result: { Signature, // 對變量policy簽名後的字符串。 policy, // 用戶表單上傳的策略(Policy),是通過base64編碼過的字符串。 host, // 用戶要往哪一個域名發送上傳請求。 OSSAccessKeyId: accessKeyId, // 用戶請求的accessid。 key: expireTime, // 惟一標識,添加到上傳的文件名中防止重複 success_action_status: 200, dirPath, // 文件上傳地址 callback, // 接口回調 }, }); }
請求回調接口安全
// 回調 async ossCallback() { const { body = {} } = this.ctx.request; // 對應簽名接口中定義的返回數據字段 const { filename, height, width } = body; if (filename) { this.ctx.body = ({ status: 200, message: '操做成功', data: `https://${config.bucket}.${config.region}.aliyuncs.com/${filename}#w=${width}#h=${height}`, }); } else { this.ctx.body = { status: 500, message: '操做失敗', data: null, }; } }