如何不依賴 SDK,用簡單的代碼,Web 端直傳文件到騰訊云COS

前提條件

登錄騰訊云COS 控制臺并創(chuàng)建存儲桶,得到 Bucket(存儲桶名稱) 和 Region(地域名稱),詳情請參見創(chuàng)建存儲桶文檔。

進入存儲桶詳情頁,單擊安全管理頁簽。下拉頁面找到跨域訪問CORS設(shè)置配置項,單擊添加規(guī)則,配置示例如下圖,詳情請參見設(shè)置跨域訪問文檔。

登錄訪問管理控制臺, 獲取您的項目 SecretId 和 SecretKey。

注意:

騰訊云COS特惠活動,新人1元起,還有更多好禮等你來揭曉!

實踐步驟

注意:

正式部署時服務(wù)端請加一層您的網(wǎng)站本身的權(quán)限檢驗。

獲取臨時密鑰和計算簽名

出于安全考慮,簽名使用臨時密鑰,服務(wù)端搭建臨時密鑰服務(wù),可參考PHP 示例、Nodejs 示例。

如有其他語言或自行實現(xiàn)可以參考以下流程:

向服務(wù)端獲取臨時密鑰,服務(wù)端首先使用固定密鑰 SecretId、SecretKey 向 STS 服務(wù)獲取臨時密鑰,得到臨時密鑰 tmpSecretId、tmpSecretKey、sessionToken,詳情請參考臨時密鑰生成及使用指引cos-sts-sdk文檔。

前端通過 tmpSecretId、tmpSecretKey,以及 method、pathname 計算簽名,可參考下文使用cos-auth.js來計算簽名,如果業(yè)務(wù)需要也可以放在后端計算簽名。

如果使用 PutObject 接口上傳文件,將計算得到的簽名和 sessionToken,分別放到發(fā)請求時 header 的 authorization 和 x-cos-security-token 字段里。

如果使用 PostObject 接口上傳文件,則將計算得到的簽名和 sessionToken,分別放到發(fā)請求時表單的 Signature 和 x-cos-security-token 字段里。

前端上傳

方案 A:使用 AJAX 上傳

AJAX 上傳需要瀏覽器支持基本的 HTML5 特性,當前方案使用PUT Object?文檔,操作指引如下:

按照前提條件的步驟,準備存儲桶的相關(guān)配置。

創(chuàng)建test.html文件,修改下方代碼的 Bucket 和 Region,并復(fù)制到test.html文件。

部署后端的簽名服務(wù),并修改test.html里的簽名服務(wù)地址。

將test.html放在 Web 服務(wù)器下,并通過瀏覽器訪問頁面,測試文件上傳功能。


Ajax Put 上傳h1,h2{font-weight: normal;? ? ? ? }#msg{margin-top:10px;? ? ? ? }

Ajax Put 上傳

(function() {// 請求用到的參數(shù)varBucket='examplebucket-1250000000';varRegion='ap-guangzhou';varprotocol = location.protocol==='https:'?'https:':'http:';varprefix = protocol +'//'+Bucket+'.cos.'+Region+'.myqcloud.com/';// prefix 用于拼接請求 url 的前綴,域名使用存儲桶的默認域名// 對更多字符編碼的 url encode 格式varcamSafeUrlEncode =function(str) {returnencodeURIComponent(str)? ? ? ? ? ? ? ? .replace(/!/g,'%21')? ? ? ? ? ? ? ? .replace(/'/g,'%27')? ? ? ? ? ? ? ? .replace(/\(/g,'%28')? ? ? ? ? ? ? ? .replace(/\)/g,'%29')? ? ? ? ? ? ? ? .replace(/\*/g,'%2A');? ? ? ? };// 計算簽名vargetAuthorization =function(options, callback) {// var url = 'http://127.0.0.1:3000/sts-auth' +varurl ='../server/sts.php';varxhr =newXMLHttpRequest();? ? ? ? ? ? xhr.open('GET', url,true);? ? ? ? ? ? xhr.onload=function(e) {varcredentials;try{? ? ? ? ? ? ? ? ? ? credentials = (newFunction('return '+ xhr.responseText))().credentials;? ? ? ? ? ? ? ? }catch(e) {}if(credentials) {callback(null, {SecurityToken: credentials.sessionToken,Authorization:CosAuth({SecretId: credentials.tmpSecretId,SecretKey: credentials.tmpSecretKey,Method: options.Method,Pathname: options.Pathname,? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? });? ? ? ? ? ? ? ? }else{console.error(xhr.responseText);callback('獲取簽名出錯');? ? ? ? ? ? ? ? }? ? ? ? ? ? };? ? ? ? ? ? xhr.onerror=function(e) {callback('獲取簽名出錯');? ? ? ? ? ? };? ? ? ? ? ? xhr.send();? ? ? ? };// 上傳文件varuploadFile =function(file, callback) {varKey='dir/'+ file.name;// 這里指定上傳目錄和文件名getAuthorization({Method:'PUT',Pathname:'/'+Key},function(err, info) {if(err) {alert(err);return;? ? ? ? ? ? ? ? }varauth = info.Authorization;varSecurityToken= info.SecurityToken;varurl = prefix +camSafeUrlEncode(Key).replace(/%2F/g,'/');varxhr =newXMLHttpRequest();? ? ? ? ? ? ? ? xhr.open('PUT', url,true);? ? ? ? ? ? ? ? xhr.setRequestHeader('Authorization', auth);SecurityToken&& xhr.setRequestHeader('x-cos-security-token',SecurityToken);? ? ? ? ? ? ? ? xhr.upload.onprogress=function(e) {console.log('上傳進度 '+ (Math.round(e.loaded/ e.total*10000) /100) +'%');? ? ? ? ? ? ? ? };? ? ? ? ? ? ? ? xhr.onload=function() {if(/^2\d\d$/.test(''+ xhr.status)) {varETag= xhr.getResponseHeader('etag');callback(null, {url: url,ETag:ETag});? ? ? ? ? ? ? ? ? ? }else{callback('文件 '+Key+' 上傳失敗,狀態(tài)碼:'+ xhr.status);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? };? ? ? ? ? ? ? ? xhr.onerror=function() {callback('文件 '+Key+' 上傳失敗,請檢查是否沒配置 CORS 跨域規(guī)則');? ? ? ? ? ? ? ? };? ? ? ? ? ? ? ? xhr.send(file);? ? ? ? ? ? });? ? ? ? };// 監(jiān)聽表單提交document.getElementById('submitBtn').onclick=function(e) {varfile =document.getElementById('fileSelector').files[0];if(!file) {document.getElementById('msg').innerText='未選擇上傳文件';return;? ? ? ? ? ? }? ? ? ? ? ? file &&uploadFile(file,function(err, data) {console.log(err || data);document.getElementById('msg').innerText= err ? err : ('上傳成功,ETag='+ data.ETag);? ? ? ? ? ? });? ? ? ? };? ? })();

執(zhí)行效果如下圖:

方案 B:使用 Form 表單上傳

Form 表單上傳支持低版本的瀏覽器的上傳(如 IE8),當前方案使用Post Object?接口。操作指引:

按照前提條件的步驟,準備存儲桶。

創(chuàng)建test.html文件,修改下方代碼的 Bucket 和 Region,并復(fù)制到test.html文件。

部署后端的簽名服務(wù),并修改test.html里的簽名服務(wù)地址。

在test.html同一個目錄下,創(chuàng)建一個空的empty.html,用于上傳成功時跳轉(zhuǎn)回來。

將test.html和empty.html放在 Web 服務(wù)器下,并通過瀏覽器訪問頁面,測試文件上傳功能。

Form 表單簡單上傳h1,h2{font-weight: normal;}#msg{margin-top:10px;}

Form 表單簡單上傳(兼容 IE8)

最低兼容到 IE6 上傳,不支持 onprogress
<!-- file 字段放在表單最后,避免文件內(nèi)容過長影響簽名判斷和鑒權(quán) -->(function() {// 請求用到的參數(shù)varBucket='examplebucket-1250000000';varRegion='ap-guangzhou';varprotocol = location.protocol==='https:'?'https:':'http:';varprefix = protocol +'//'+Bucket+'.cos.'+Region+'.myqcloud.com/';// prefix 用于拼接請求 url 的前綴,域名使用存儲桶的默認域名varform =document.getElementById('form');? ? ? ? form.action= prefix;// 對更多字符編碼的 url encode 格式varcamSafeUrlEncode =function(str) {returnencodeURIComponent(str)? ? ? ? ? ? ? ? .replace(/!/g,'%21')? ? ? ? ? ? ? ? .replace(/'/g,'%27')? ? ? ? ? ? ? ? .replace(/\(/g,'%28')? ? ? ? ? ? ? ? .replace(/\)/g,'%29')? ? ? ? ? ? ? ? .replace(/\*/g,'%2A');? ? ? ? };// 計算簽名vargetAuthorization =function(options, callback) {// var url = 'http://127.0.0.1:3000/sts' +varurl ='../server/sts.php';varxhr =newXMLHttpRequest();? ? ? ? ? ? xhr.open('GET', url,true);? ? ? ? ? ? xhr.onreadystatechange=function(e) {if(xhr.readyState===4) {if(/^2\d\d$/.test(''+ xhr.status)) {varcredentials;try{? ? ? ? ? ? ? ? ? ? ? ? ? ? credentials = (newFunction('return '+ xhr.responseText))().credentials;? ? ? ? ? ? ? ? ? ? ? ? }catch(e) {}if(credentials) {callback(null, {SecurityToken: credentials.sessionToken,Authorization:CosAuth({SecretId: credentials.tmpSecretId,SecretKey: credentials.tmpSecretKey,Method: options.Method,Pathname: options.Pathname,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? ? ? ? ? ? ? });? ? ? ? ? ? ? ? ? ? ? ? }else{console.error(xhr.responseText);callback('獲取簽名出錯');? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }else{callback('獲取簽名出錯');? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? };? ? ? ? ? ? xhr.send();? ? ? ? };// 監(jiān)聽上傳完成varKey;varsubmitTarget =document.getElementById('submitTarget');varshowMessage =function(err, data) {console.log(err || data);document.getElementById('msg').innerText= err ? err : ('上傳成功,ETag='+ data.ETag);? ? ? ? };? ? ? ? submitTarget.onload=function() {varsearch;try{? ? ? ? ? ? ? ? search = submitTarget.contentWindow.location.search.substr(1);? ? ? ? ? ? }catch(e) {showMessage('文件 '+Key+' 上傳失敗');? ? ? ? ? ? }if(search) {varitems = search.split('&');vari, arr, data = {};for(i =0; i

執(zhí)行效果如下圖:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 業(yè)務(wù)背景 筆者有一個簡單的純靜態(tài)文檔站點docs.ioiox.com,使用的是docsify項目的Markdo...
    粵海科技君閱讀 655評論 0 0
  • JSV5 1、vue 雙向綁定的原理 通過object.defineProperty()方法來劫持屬性的gette...
    merlinxu閱讀 1,313評論 0 1
  • 之前有做過iOS的Cos上傳文件,小程序的是第一次做.在網(wǎng)上找了好多資料素材.JS的有很多可以參考,但是關(guān)于小程序...
    Mr_Atom閱讀 7,093評論 1 8
  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實...
    他方l閱讀 1,134評論 0 2
  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實...
    HeroXin閱讀 954評論 0 4

友情鏈接更多精彩內(nèi)容