<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在日常開發中,使用者端上傳檔案的一般流程是:使用者端向伺服器端傳送檔案,再由伺服器端將檔案轉儲到專門的儲存伺服器或雲端計算廠商的儲存服務(例如阿里雲 OSS)上,這樣做的一個弊端是上傳環節佔用伺服器的頻寬,個位數的並行上傳就能把頻寬佔滿,從而導致使用者體驗下降。而如果直接將檔案從使用者端直傳到第三方的儲存服務上,就可以避免這個問題。
本文以阿里雲 OSS(Object Storage Service,物件儲存服務)為例,詳細說明將檔案從使用者端直傳 OSS 的整體流程,並提供了完整的程式碼演示。
從“使用者端 — 伺服器 — OSS”的傳輸模式,變更為“使用者端 — OSS”的模式,最大的好處是,省掉了上傳伺服器的這一步,上傳效率更高,速度更快(相比較於一般伺服器的頻寬,可以認為 OSS 的寬頻是“幾乎無限”的)。
當然該模式也有缺點,那就是增加了很多額外的開發工作量,主要包含 2 部分:
(1)伺服器端增加生成上傳 OSS 憑證的程式碼。
(2)使用者端增加從伺服器端獲取上傳 OSS 憑證的程式碼和對直傳 OSS 進行適配。
整體而言,直傳模式除了增加一點開發工作量以外,從架構層面,幾乎沒有任何缺點。
實際上,整個流程非常簡單,包含了兩步:
(1)使用者端向伺服器端傳送請求,獲取直傳 OSS 的憑證。
(2)使用者端向 OSS 上傳檔案,並攜帶該憑證。
關於如何生成憑證(也叫簽名),可以閱讀官方檔案(help.aliyun.com/document_de…),但由於檔案建立時間比較早,對於新手很難看懂,本文將手把手給你演示整個過程。
整個“生成上傳 OSS 憑證”過程,實際上做了這麼幾件事:
(1)上傳憑證鑑權由 policy
提供,根據私密設定生成這個 policy
。
(2)由於上傳環節脫離了開發者伺服器,因此你可以在 policy
中定義各種限制,例如上傳最大體積、檔名等。
(3)將 policy
轉化為指定的格式。
我們先考慮將流程的每一步實現,然後再將流程程式碼封裝成函數。
首先定義 OSS 的組態檔,關於設定項的內容,可以參考檔案:help.aliyun.com/document_de…
/** OSS 設定項 */ const ossConfig = { bucket: 'xxxxxxxx', accessKeyId: 'xxxxxxxx', accessKeySecret: 'xxxxxxxx', /** OSS 繫結的域名 */ url: 'xxxxxxxx', }
對於 policy
,有很多設定項,我們先考慮生成“寫死”的模式,然後再優化為由函數引數傳入設定項。以下是一個最基礎的 policy
。
首先定義一個有效時長(單位:毫秒),然後該憑證的有效截止時間則為“當前時間 + 有效時長”,最後需要轉化為 ISO 時間字串格式。
/** 有效時長:例如 4 小時 */ const timeout = 4 * 60 * 60 * 1000 /** 到期時間:當前時間 + 有效時間 */ const expiration = new Date(Date.now() + timeout).toISOString()
檔名建議使用 UUID(筆者習慣性使用去掉短橫線的 UUID),避免重複。
import { v4 as uuidv4 } from 'uuid' /** 隨機檔名(去掉短橫線的 uuid) */ const filename = uuidv4().replace(/-/gu, '')
一般建議按照不同的業務模組,將檔案劃分不同的目錄,例如這裡使用 file
目錄,那麼完整的 OSS 檔案路徑則為:
/** 目錄名稱 */ const dirname = 'file' /** 檔案路徑 */ const key = dirname + '/' + filename
需要注意的是,檔案路徑不能以 “/” 開頭(OSS 本身的要求)。
將以上內容整合,就形成了 policy
文字,以下是一個基礎格式:
const policyText = { expiration: expiration, conditions: [ ['eq', '$bucket', ossConfig.bucket], ['eq', '$key', key], ], }
將 policyText
轉化為 Base64
格式後,就是要求的 policy
了。
// 將 policyText 轉化為 Base64 格式 const policy = Buffer.from(JSON.stringify(policyText)).toString('base64')
然後對 policy
使用 OSS 金鑰使用 HmacSha1 演演算法簽名簽名。
import * as crypto from 'crypto' // 使用 HmacSha1 演演算法簽名 const signature = crypto.createHmac('sha1', ossConfig.accessKeySecret).update(policy, 'utf8').digest('base64')
最後將上述流程中的相關欄位返回給使用者端,即為“上傳憑證”。
以上完整演示了整個流程,我們進一步分析,如何將其封裝為一個通用性的函數。
(1)憑證的有效時長可以根據不同的業務模組分別定義,於是做成函數設定項。
(2)目錄名稱也可以做成設定項。
(3) policy
還有更多的設定內容(見檔案 help.aliyun.com/document_de…),可以抽取一部分做成設定項,例如“允許上傳的最大體積”。
以下是封裝為“服務”的使用 Nest.js
Web 框架的相關程式碼,來源自筆者的線上專案(略有調整和刪改),供參考。
import { Injectable } from '@nestjs/common' import * as crypto from 'crypto' import { v4 as uuidv4 } from 'uuid' export interface GenerateClientTokenConfig { /** 目錄名稱 */ dirname: string /** 有效時間,單位:小時 */ expiration?: number /** 上傳最大體積,單位:MB */ maxSize?: number } /** 直傳憑證 */ export interface ClientToken { key: string policy: string signature: string OSSAccessKeyId: string url: string } export interface OssConfig { bucket: string accessKeyId: string accessKeySecret: string url: string } @Injectable() export class OssService { private readonly ossConfig: OssConfig constructor() { this.ossConfig = { bucket: 'xxxxxxxx', accessKeyId: 'xxxxxxxx', accessKeySecret: 'xxxxxxxx', /** OSS 繫結的域名 */ url: 'xxxxxxxx', } } /** * 生成一個可用於使用者端直傳 OSS 的呼叫憑證 * * @param config 設定項 * * @see [設定內容](https://help.aliyun.com/document_detail/31988.html) */ generateClientToken(config: GenerateClientTokenConfig): ClientToken { /** 目錄名稱 */ const dirname = config.dirname /** 有效時間:預設 4 小時 */ const timeout = (config.expiration || 4) * 60 * 60 * 1000 /** 上傳最大體積,預設 100M */ const maxSize = (config.maxSize || 100) * 1024 * 1024 /** 隨機檔名(去掉短橫線的 uuid) */ const filename = uuidv4().replace(/-/gu, '') /** 檔案路徑 */ const key = dirname + '/' + filename /** 到期時間:當前時間 + 有效時間 */ const expiration = new Date(Date.now() + timeout).toISOString() const { bucket, url, accessKeyId } = this.ossConfig const policyText = { expiration: expiration, conditions: [ ['eq', '$bucket', bucket], ['eq', '$key', key], ['content-length-range', 0, maxSize], ], } // 將 policyText 轉化為 Base64 格式 const policy = Buffer.from(JSON.stringify(policyText)).toString('base64') // 使用 HmacSha1 演演算法簽名 const signature = crypto.createHmac('sha1', this.ossConfig.accessKeySecret).update(policy, 'utf8').digest('base64') return { key, policy, signature, OSSAccessKeyId: accessKeyId, url } } }
在完整以上服務方法後,後續就可以在“控制器”層呼叫該方法用於分發上傳憑證,使用者端可直接使用該上傳憑證將檔案直傳至 OSS 中。
以上就是阿里雲OSS實踐檔案直傳基於伺服器端的詳細內容,更多關於OSS檔案直傳伺服器端的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45