自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端如何進(jìn)行單文件上傳云服務(wù)存儲(chǔ)

開發(fā) 前端
不知道大家日常使用的上傳方式是否和我們團(tuán)隊(duì)一致,之前上傳文件方案中,我司后端團(tuán)隊(duì)會(huì)提供一個(gè)后端上傳服務(wù)接口,前端直接使用這個(gè)接口進(jìn)行文件上傳,后端接受到完整文件后,會(huì)再通過調(diào)用云文件服務(wù)提供的后端 Java SDK 進(jìn)行文件上傳。

前端如何進(jìn)行單文件上傳云服務(wù)存儲(chǔ)

http://zoo.zhengcaiyun.cn/blog/article/cloudservicestorage

在日常的開發(fā)過程中,我相信大家肯定會(huì)碰到很多的文件上傳需求,例如流程中的附件,設(shè)置頭像圖片等等內(nèi)容,并且上傳的文件,為了前端頁面的加載性能,一般也都會(huì)選擇將文件上傳至云服務(wù)存儲(chǔ)當(dāng)中去,之后直接使用文件的 cdn 路徑來訪問。那么問題來了,對(duì)于文件如何上傳到云服務(wù)存儲(chǔ)當(dāng)中去大家是否了解呢?上傳流程有遇到什么困難嗎,所以這篇文章也借著我們團(tuán)隊(duì)遇到的一些問題,跟大家交流一下云服務(wù)文件存儲(chǔ)當(dāng)中的一些問題與解決方式。

目前常用的上傳方式

后端上傳

不知道大家日常使用的上傳方式是否和我們團(tuán)隊(duì)一致,之前上傳文件方案中,我司后端團(tuán)隊(duì)會(huì)提供一個(gè)后端上傳服務(wù)接口,前端直接使用這個(gè)接口進(jìn)行文件上傳,后端接受到完整文件后,會(huì)再通過調(diào)用云文件服務(wù)提供的后端 Java SDK 進(jìn)行文件上傳

圖片

這個(gè)方案的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):前端所有使用的上傳接口統(tǒng)一,前端統(tǒng)一對(duì)接公司內(nèi)部的上傳服務(wù),后端上傳服務(wù)再去對(duì)接各個(gè)不同的云存儲(chǔ)服務(wù)廠家,保證文件上傳

缺點(diǎn):后端服務(wù)需要接受所有的文件上傳的流量,然后再次進(jìn)行上傳,服務(wù)器壓力比較大。

基于上面提到的缺點(diǎn),在經(jīng)歷過服務(wù)器壓力過大,導(dǎo)致幾次大文件上傳失敗、各種外地網(wǎng)絡(luò)延遲導(dǎo)致超時(shí)故障之后,痛定思痛,決定要重新調(diào)整上傳的方式。

前端上傳

既然后端服務(wù)上傳需要走流程傳輸導(dǎo)致資源壓力過大,那是否可以可以將壓力轉(zhuǎn)移到用戶側(cè),使用用戶的瀏覽器直連云存儲(chǔ)服務(wù)進(jìn)行上傳呢?答案是當(dāng)然可以,不然也就沒有本文了。

在翻閱了幾個(gè)不同的云服務(wù)的上傳文檔后發(fā)現(xiàn),目前主流常用的前端上傳方案會(huì)分為兩種方式:

  1. 前端調(diào)用各大云服務(wù)的 JavaScript SDK 進(jìn)行上傳
  1. 優(yōu)點(diǎn):無需后端服務(wù)介入,直接調(diào)用各個(gè)云服務(wù) SDK 方法使用即可
  2. 缺點(diǎn):前端需要獲取各個(gè)云服務(wù)的 AK (AccessKey ID),SK (AccessKey Secret) 等賬號(hào)信息,并且會(huì)暴漏在代碼中,并且各個(gè)云服務(wù)場(chǎng)景會(huì)有對(duì)應(yīng)的 SDK 以及調(diào)用方式,全部做了集成的話,包的體積可能不可控,并且有些云服務(wù)商,沒有提供前端使用的SDK。
  1. 云服務(wù)會(huì)提供臨時(shí)授權(quán)的 URL,前端可以直接通過這個(gè)授權(quán) URL 訪問云服務(wù),進(jìn)行文件上傳
  2. 優(yōu)點(diǎn):前端不需要獲取云服務(wù)的 AK (AccessKey ID),SK (AccessKey Secret) 信息,統(tǒng)一由后端接口提供對(duì)應(yīng)上傳所需的請(qǐng)求地址,數(shù)據(jù)格式即可,前端通過一個(gè)接口獲取這些信息后,調(diào)用上傳即可

  3. 缺點(diǎn):各家云服務(wù)上傳所需的數(shù)據(jù)格式都不相同,前端需要調(diào)研,解析這個(gè)數(shù)據(jù)格式

上傳示例

下面以大家常用的阿里云舉例

SDK上傳

webpack打包類型項(xiàng)目,可以先通過 npm install ali-oss 安裝 SDK,以下為上傳數(shù)據(jù)到 examplebucket 中 exampledir 目錄下的exampleobject.txt 文件的代碼示例

const OSS = require('ali-oss');

const client = new OSS({
  // 以下為初始化參數(shù)
  region: 'yourRegion',
  // 從 STS 服務(wù)獲取的臨時(shí)訪問密鑰(AccessKey ID和AccessKey Secret)。
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  // 從STS服務(wù)獲取的安全令牌(SecurityToken)。
  stsToken: 'yourSecurityToken',
  // 填寫 Bucket 名稱(可以簡(jiǎn)單理解為,你上傳不同文件到不同的文件夾命名)。
  bucket: 'examplebucket'
});
// 從輸入框獲取 file 對(duì)象,例如 <input type="file" id="file" />。
let data;
// 創(chuàng)建并填寫 Blob 數(shù)據(jù)。
//const data = new Blob(['Hello OSS']);
// 創(chuàng)建并填寫 OSS Buffer內(nèi)容。
//const data = new OSS.Buffer(['Hello OSS']);
const upload = document.getElementById("upload");
const headers = {
  // 以下為上傳時(shí)可以設(shè)置的一些 header 數(shù)據(jù),不同云服務(wù)需要的不同,具體參考各個(gè)版本文檔
  // 'Content-Type': 'text/html', // 指定上傳文件的類型。
  // 'Cache-Control': 'no-cache',  // 指定該 Object 被下載時(shí)網(wǎng)頁的緩存行為。
  // 'Content-Disposition': 'oss_download.txt',  // 指定該 Object 被下載時(shí)的名稱。
  // 'Content-Encoding': 'UTF-8',  // 指定該 Object 被下載時(shí)的內(nèi)容編碼格式。
  // 'Expires': 'Wed, 08 Jul 2022 16:57:01 GMT',  // 指定過期時(shí)間。
  // 'x-oss-storage-class': 'Standard',  // 指定 Object 的存儲(chǔ)類型。
  // 'x-oss-object-acl': 'private',  // 指定 Object 的訪問權(quán)限。
};
async function putObject(data) {
  try {
    // 填寫Object完整路徑。Object 完整路徑中不能包含 Bucket 名稱。
    // 您可以通過自定義文件名(例如 exampleobject.txt )或文件完整路徑(例如 exampledir/exampleobject.txt )的形式實(shí)現(xiàn)將數(shù)據(jù)上傳到當(dāng)前 Bucket 或 Bucket 中的指定目錄。
    // data 對(duì)象可以自定義為 file 對(duì)象、Blob 數(shù)據(jù)或者 OSS Buffer。
    const result = await client.put(
      "exampledir/exampleobject.txt",
      data
      //{headers}
    );
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}
upload.addEventListener("click", () => {
  data = document.getElementById("file").files[0];
  putObject(data);
});

直接調(diào)用 SDK 中提供的 put 等方法即可完成文件上傳

臨時(shí) URL 上傳(STS 臨時(shí)授權(quán))

鑒于 SDK 上傳方案中,會(huì)在代碼中暴漏 AK (AccessKey ID),SK (AccessKey Secret)  等云服務(wù)數(shù)據(jù),所以云服務(wù)廠家一般也會(huì)提供生成臨時(shí)令牌的方式,可以由后端服務(wù)生成一個(gè)自定義時(shí)效以及權(quán)限的訪問憑證提供給前端進(jìn)行上傳,有效期到期后,這個(gè)訪問令牌就會(huì)失效,保證了前端上傳的安全性。

圖片

1. 客戶端向自己的后端應(yīng)用發(fā)起請(qǐng)求,將文件類型,名稱信息等傳給后端,獲取對(duì)應(yīng)的上傳信息以及授權(quán)簽名信息 signature 等,

const UploadParams = {
  "accessid":"LTAI5tBDFVar1hoq****",
  "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com",
  "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8i****",
  "signature":"VsxOcOudx******z93CLaXPz+4s=",
  "expire":1446727949,
  "dir":"user-dirs/"
}

2. 在獲取到服務(wù)器返回的簽名信息等內(nèi)容后,客戶端則可以通過 POST 或者 PUT 請(qǐng)求直接向云服務(wù)發(fā)送上傳文件的請(qǐng)求(上傳形式多種多樣,并且有些云服務(wù)有要求上傳數(shù)據(jù)類型為 form-data 格式)

// form-data 類型
let params = {
   // key表示上傳到 Bucket 內(nèi)的 Object 的完整路徑,例如 exampledir/exampleobject.txtObject,完整路徑中不能包含 Bucket 名稱。
   // filename 表示待上傳的本地文件名稱。
   'key' : key + '${filename}',
   'policy': UploadParams.policy,
   'OSSAccessKeyId': UploadParams.accessid,
   // 設(shè)置服務(wù)端返回狀態(tài)碼為200,不設(shè)置則默認(rèn)返回狀態(tài)碼204。
   'success_action_status' : '200',    
   'signature': UploadParams.signature,
}
let requestData = new FormData();

Object.keys(params).map(key => {
  requestData.append(key, params[key]);
});
// 獲取的上傳 file 文件,file 必須為最后一個(gè)表單域,除 file 以外的其他表單域無順序要求
requestData.append('file', fileObj);

// 非 form-data 類型(非阿里云云服務(wù)會(huì)遇到,以下代碼僅舉例,不代表真實(shí)使用場(chǎng)景)
let requestData = fileObj;
let headers = {
   'key' : key + '${filename}',
   'policy': UploadParams.policy,
   'OSSAccessKeyId': UploadParams.accessid,
   'success_action_status' : '200',    
   'signature': UploadParams.signature,
}

// 進(jìn)行接口請(qǐng)求,上傳文件
axios({
  method: 'post',
  url: params.host,
  data: requestData,
  headers: headers || {},
});

這里代碼只是簡(jiǎn)單的示例,實(shí)際使用時(shí)需要對(duì)各個(gè)文件服務(wù)需要進(jìn)行不同的適配。

加密算法和解析

對(duì)于獲取 Signature 鑒權(quán)信息等內(nèi)容時(shí),后端服務(wù)在有文檔或者 SDK 時(shí),可以對(duì)接不同的云服務(wù) JAVA SDK 直接進(jìn)行生成臨時(shí)授權(quán)的信息,在沒有文檔的情況下,則需要前端或者后端,針對(duì)各個(gè)不同的云服務(wù),進(jìn)行解析加密 Signature 的步驟(我司這里是前端進(jìn)行了加密過程解析后,后續(xù)日常生成由后端服務(wù)完成)。

加密算法

此處我以紫光云的 Signature 生成步驟給大家簡(jiǎn)單介紹下加密算法的流程,不同的云服務(wù),加密過程都比較類似。

圖片

圖片來源:紫光云上傳流程(https://www.unicloud.com/document/show-19262078.html)

以下是根據(jù)上述的加密流程寫的測(cè)試生成 Signature 的代碼部分,大家也可以自行測(cè)試試用。

按流程主要分成3步即可

  1. 生成 CanonicalRequest 字段
  2. 生成前面的 StringToSign
  3. 根據(jù) AK (AccessKey ID),SK (AccessKey Secret)  生成 Signature,最后組裝 Authorization。
const crypto = require('crypto');
const CryptoJS = require('crypto-js')

function zip() {
  const filename = 'uploadTest.png'
  // const date = new Date()
  // const timeStampISO8601Format = `${date.toISOString().replace(/-/g, '').replace(/:/g, '').split('.')[0]}Z` // ISO 8601 格式
  const timeStampISO8601Format = '20230101T000000Z' // ISO 8601 格式
  const dateString = timeStampISO8601Format.substr(0, 8) // YYYYMMDD 格式時(shí)間

  const uriFileName = uriEscapePath(filename)
  const content = 'UNSIGNED-PAYLOAD'
  
  // 生成 CanonicalRequest 字段
  let CanonicalRequest = `PUT\n${uriFileName}\n\ncontent-disposition:attachment;filename=uploadTest.png\ncontent-type:image/png\nhost:oos-cn.ctyunapi.cn\nx-amz-content-sha256:${content}\nx-amz-date:${timeStampISO8601Format}\n\ncontent-disposition;content-type;host;x-amz-content-sha256;x-amz-date\n${content}`
  let hashedCanonicalRequest = crypto.createHash('sha256').update(CanonicalRequest).digest('hex');

  // 生成前面的 StringToSign
  const signStr = `AWS4-HMAC-SHA256\n${timeStampISO8601Format}\n${dateString}/cn/s3/aws4_request\n${hashedCanonicalRequest}`
  //根據(jù) AK (AccessKey ID),SK (AccessKey Secret) 生成 Signature
  const AWSAccessKeyId = 'AWSAccessKeyId';
  const AWSSecretAccessKey = 'AWSSecretAccessKey';

  var DateKey = CryptoJS.HmacSHA256(dateString, `AWS4${AWSSecretAccessKey}`);
  var DateRegionKey = CryptoJS.HmacSHA256('cn', DateKey);
  var DateRegionServiceKey = CryptoJS.HmacSHA256('s3', DateRegionKey);
  var SigningKey = CryptoJS.HmacSHA256('aws4_request', DateRegionServiceKey);
  var Signature = CryptoJS.HmacSHA256(signStr, SigningKey);
  console.log('?? ~ Signature==', `${Signature}`);

  // 最后上傳需要的 Authorization 數(shù)據(jù)
  let Authorization = `AWS4-HMAC-SHA256 Credential=${AWSAccessKeyId}/${dateString}/cn/s3/aws4_request, SignedHeaders=content-disposition;content-type;host;x-amz-content-sha256;x-amz-date, Signature=${Signature}`
  console.log('?? ~ Authorizatinotallow==', Authorization)
}

try {
  zip()
} catch (error) {
  console.log('?? ~ error', error)
}

// uriEncode 方法
function uriEscapePath(string) {
  var parts = [];
  arrayEach(string.split("/"), function (part) {
    parts.push(uriEscape(part));
  });
  return parts.join("/");
}

function uriEscape(string) {
  var output = encodeURIComponent(string);
  output = output.replace(/[^A-Za-z0-9_.~\-%]+/g, escape);
  output = output.replace(/[*]/g, function (ch) {
    return "%" + ch.charCodeAt(0).toString(16).toUpperCase();
  });
  return output;
}

function arrayEach(array, iterFunction) {
  for (var idx in array) {
    if (Object.prototype.hasOwnProperty.call(array, idx)) {
      var ret = iterFunction.call(this, array[idx], parseInt(idx, 10));
      if (ret === {}) break;
    }
  }
}

常用云服務(wù)上傳格式 下面也提供了一些常用云服務(wù)上傳格式,上傳需要的最基礎(chǔ)格式,按照這個(gè)格式,組裝出需要的數(shù)據(jù),然后發(fā)起上傳請(qǐng)求即可。下文示例中,如果使用 data 數(shù)據(jù)類型來進(jìn)行校驗(yàn)權(quán)限,上傳基本都是采用 form-data 數(shù)據(jù)封裝,上傳的 File 文件。而如果使用的是 headers 的類型進(jìn)行數(shù)據(jù)校驗(yàn),上傳的 File 文件直接賦值請(qǐng)求中的 data 字段即可。

阿里云

{
  "method":"POST", // 上傳的請(qǐng)求類型
  "dataType":"formData", // 為了區(qū)分上傳數(shù)據(jù)的 form-data 類型,可自己任意定義
  "data":{ //
      "OSSAccessKeyId":"accessKeyId",
      "signature":"計(jì)算后簽名Signature",
      "success_action_status":"200",
      "Content-Disposition":"attachment;filename=encodeURI(filename)",
      "key":"上傳文件路徑/上傳的文件fileId",
      "policy":"后端返回的policy",
      "file": File, // 上傳的 file 文件
  },
  "action":"上傳服務(wù)的域名" // 前端發(fā)起上傳的請(qǐng)求 URL
}

華為云

{
  "headers":{
    "X-Requested-With":null,
    "Content-Disposition":"attachment;filename=encodeURI(filename)",
    "Content-Type":"文件類型"
  },
  "method":"PUT",
  "data": File, // 上傳的 file 文件
  "dataType":"text",// 為了區(qū)分上傳數(shù)據(jù)的 form-data 類型,可自己任意定義
  "action":"https://上傳服務(wù)url域名/bucket/${fileId}?AccessKeyId=${AccessKeyId}&Expires=${過期時(shí)間}&Signature=${計(jì)算后簽名Signature}",
  "fileId":"文件名稱,可以使用唯一id"
}

電信云 / 紫光云

{
  "headers":{
    "Authorization":"AWS4-HMAC-SHA256 Credential=<your-access-key-id>/<date>/<aws-region>/<aws-service>/aws4_request , SignedHeaders=content-disposition;content-type;host;x-amz-content-sha256;x-amz-date, Signature=${計(jì)算后前面Signature}",
    "x-amz-content-sha256":"UNSIGNED-PAYLOAD",
    "x-amz-date":"20230202T093208Z(服務(wù)器時(shí)間)",
    "Content-Disposition":"attachment;filename=encodeURI(fileName)",
    "Content-Type":"文件類型"
  },
  "method":"PUT",
  "data": File, // 上傳的 file 文件
  "dataType":"text",
  "action":"https://上傳服務(wù)url域名/bucket/${fileId}"
}

從這幾種云服務(wù)的類型可以看出,上傳參數(shù)區(qū)分,基本分為了data 數(shù)據(jù)校驗(yàn)上傳或者 headers 校驗(yàn)上傳,上面的文件上傳實(shí)例代碼基本可以包括目前的幾種上傳請(qǐng)求方式

上傳推薦

以上兩種方式都可以滿足前端直連上傳的需求,大家選擇的時(shí)候可以根據(jù)自己的實(shí)際場(chǎng)景進(jìn)行選擇即可。

當(dāng)你的上傳云服務(wù)比較單一,無論是 SDK 上傳,或者臨時(shí)授權(quán) URL 上傳都可以選擇,不過如果對(duì)賬號(hào)安全比較敏感,第一種方式也可以選擇加密或者配置數(shù)據(jù)的方式進(jìn)行賬號(hào)的傳遞。

而鑒于我司有多種云服務(wù)上傳的需求,并且 SDK 上傳方式需要暴漏 AK (AccessKey ID),SK (AccessKey Secret) 等業(yè)務(wù)數(shù)據(jù), SDK 的集成也會(huì)使后續(xù)輸出的 NPM 包依賴內(nèi)容過大,還需要兼容不同 SDK不同的上傳調(diào)用方法,所以我司最后是選擇了臨時(shí)授權(quán) URL 的方式進(jìn)行處理,一方面,服務(wù)商敏感數(shù)據(jù)可以放在后端服務(wù)進(jìn)行統(tǒng)一維護(hù)處理,另一方面,前端對(duì)于不同云服務(wù)上傳的配置數(shù)據(jù)進(jìn)行統(tǒng)一的兼容處理,在發(fā)起后續(xù)的上傳,代碼邏輯也會(huì)比較的統(tǒng)一。

總結(jié)

本文僅針對(duì)了單文件上傳進(jìn)行了梳理,對(duì)于多文件、分片上傳等還未涉及,后續(xù)還會(huì)繼續(xù)分享。不知道大家對(duì)于對(duì)接云服務(wù)上傳是否還有其他更好的處理方式,歡迎一起討論一下。

參考鏈接

阿里云 SDK 上傳(https://help.aliyun.com/document_detail/383950.html)

阿里云 PostObject 解析(https://help.aliyun.com/document_detail/31988.htm?spm=a2c4g.11186623.0.0.160750c5esmHVG#section-d5z-1ww-wdb)

阿里云后端簽名后直傳(https://help.aliyun.com/document_detail/31926.html)

華為云臨時(shí)授權(quán) url 訪問(https://support.huaweicloud.com/sdk-browserjs-devg-obs/obs_24_0801.html)

電信云鑒權(quán)加密方式(https://www.ctyun.cn/document/10026693/10027129)

紫光云鑒權(quán)加密方式(https://www.unicloud.com/document/show-19262078.html)

圖片

責(zé)任編輯:武曉燕 來源: 政采云技術(shù)
相關(guān)推薦

2022-10-10 09:11:12

互聯(lián)網(wǎng)存儲(chǔ)系統(tǒng)云計(jì)算

2021-12-14 22:12:30

云計(jì)算云存儲(chǔ)IT

2023-03-24 16:18:08

微服務(wù)架構(gòu)

2011-10-26 11:21:47

服務(wù)器虛擬化存儲(chǔ)管理

2011-07-04 10:20:25

服務(wù)器云時(shí)代

2022-03-14 18:29:34

云合規(guī)監(jiān)控云平臺(tái)

2010-01-27 10:45:21

C++單例模式

2012-10-15 09:30:04

CSSDIVWeb

2011-09-01 18:54:29

WifiGoodReader

2010-03-09 18:14:55

Python sock

2011-07-25 10:48:34

服務(wù)器虛擬服務(wù)器

2010-02-02 13:04:03

C++頭文件

2010-07-22 16:13:53

2022-05-25 15:33:27

區(qū)塊鏈加密貨幣

2016-12-12 16:17:22

華為

2022-03-24 13:55:37

云計(jì)算合規(guī)性監(jiān)控工具

2019-04-18 10:20:44

2015-09-11 09:39:51

云計(jì)算

2010-08-05 09:46:45

FlexAIR文件打包

2010-03-12 19:29:15

python svn腳
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)