您当前的位置:首页 > 电脑百科 > 程序开发 > 前端

前端如何进行单文件上传云服务存储

时间:2023-06-01 14:14:57  来源:政采云技术  作者:

在日常的开发过程中,我相信大家肯定会碰到很多的文件上传需求,例如流程中的附件,设置头像图片等等内容,并且上传的文件,为了前端页面的加载性能,一般也都会选择将文件上传至云服务存储当中去,之后直接使用文件的 cdn 路径来访问。那么问题来了,对于文件如何上传到云服务存储当中去大家是否了解呢?上传流程有遇到什么困难吗,所以这篇文章也借着我们团队遇到的一些问题,跟大家交流一下云服务文件存储当中的一些问题与解决方式。

目前常用的上传方式

后端上传

不知道大家日常使用的上传方式是否和我们团队一致,之前上传文件方案中,我司后端团队会提供一个后端上传服务接口,前端直接使用这个接口进行文件上传,后端接受到完整文件后,会再通过调用云文件服务提供的后端 JAVA SDK 进行文件上传

图片

这个方案的优缺点

优点:前端所有使用的上传接口统一,前端统一对接公司内部的上传服务,后端上传服务再去对接各个不同的云存储服务厂家,保证文件上传

缺点:后端服务需要接受所有的文件上传的流量,然后再次进行上传,服务器压力比较大。

基于上面提到的缺点,在经历过服务器压力过大,导致几次大文件上传失败、各种外地网络延迟导致超时故障之后,痛定思痛,决定要重新调整上传的方式。

前端上传

既然后端服务上传需要走流程传输导致资源压力过大,那是否可以可以将压力转移到用户侧,使用用户的浏览器直连云存储服务进行上传呢?答案是当然可以,不然也就没有本文了。

在翻阅了几个不同的云服务的上传文档后发现,目前主流常用的前端上传方案会分为两种方式:

  1. 前端调用各大云服务的 JavaScript SDK 进行上传
  1. 优点:无需后端服务介入,直接调用各个云服务 SDK 方法使用即可
  2. 缺点:前端需要获取各个云服务的 AK (AccessKey ID),SK (AccessKey Secret) 等账号信息,并且会暴漏在代码中,并且各个云服务场景会有对应的 SDK 以及调用方式,全部做了集成的话,包的体积可能不可控,并且有些云服务商,没有提供前端使用的SDK。
  1. 云服务会提供临时授权的 URL,前端可以直接通过这个授权 URL 访问云服务,进行文件上传
  2. 优点:前端不需要获取云服务的 AK (AccessKey ID),SK (AccessKey Secret) 信息,统一由后端接口提供对应上传所需的请求地址,数据格式即可,前端通过一个接口获取这些信息后,调用上传即可

  3. 缺点:各家云服务上传所需的数据格式都不相同,前端需要调研,解析这个数据格式

上传示例

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

SDK上传

webpack打包类型项目,可以先通过 npm install ali-oss 安装 SDK,以下为上传数据到 examplebucket 中 exampledir 目录下的exampleobject.txt 文件的代码示例

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

const client = new OSS({
  // 以下为初始化参数
  region: 'yourRegion',
  // 从 STS 服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  // 从STS服务获取的安全令牌(SecurityToken)。
  stsToken: 'yourSecurityToken',
  // 填写 Bucket 名称(可以简单理解为,你上传不同文件到不同的文件夹命名)。
  bucket: 'examplebucket'
});
// 从输入框获取 file 对象,例如 <input type="file" id="file" />。
let data;
// 创建并填写 Blob 数据。
//const data = new Blob(['Hello OSS']);
// 创建并填写 OSS Buffer内容。
//const data = new OSS.Buffer(['Hello OSS']);
const upload = document.getElementById("upload");
const headers = {
  // 以下为上传时可以设置的一些 header 数据,不同云服务需要的不同,具体参考各个版本文档
  // 'Content-Type': 'text/html', // 指定上传文件的类型。
  // 'Cache-Control': 'no-cache',  // 指定该 Object 被下载时网页的缓存行为。
  // 'Content-Disposition': 'oss_download.txt',  // 指定该 Object 被下载时的名称。
  // 'Content-Encoding': 'UTF-8',  // 指定该 Object 被下载时的内容编码格式。
  // 'Expires': 'Wed, 08 Jul 2022 16:57:01 GMT',  // 指定过期时间。
  // 'x-oss-storage-class': 'Standard',  // 指定 Object 的存储类型。
  // 'x-oss-object-acl': 'private',  // 指定 Object 的访问权限。
};
async function putObject(data) {
  try {
    // 填写Object完整路径。Object 完整路径中不能包含 Bucket 名称。
    // 您可以通过自定义文件名(例如 exampleobject.txt )或文件完整路径(例如 exampledir/exampleobject.txt )的形式实现将数据上传到当前 Bucket 或 Bucket 中的指定目录。
    // data 对象可以自定义为 file 对象、Blob 数据或者 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);
});

直接调用 SDK 中提供的 put 等方法即可完成文件上传

临时 URL 上传(STS 临时授权)

鉴于 SDK 上传方案中,会在代码中暴漏 AK (AccessKey ID),SK (AccessKey Secret)  等云服务数据,所以云服务厂家一般也会提供生成临时令牌的方式,可以由后端服务生成一个自定义时效以及权限的访问凭证提供给前端进行上传,有效期到期后,这个访问令牌就会失效,保证了前端上传的安全性。

图片

1. 客户端向自己的后端应用发起请求,将文件类型,名称信息等传给后端,获取对应的上传信息以及授权签名信息 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. 在获取到服务器返回的签名信息等内容后,客户端则可以通过 POST 或者 PUT 请求直接向云服务发送上传文件的请求(上传形式多种多样,并且有些云服务有要求上传数据类型为 form-data 格式)

// form-data 类型
let params = {
   // key表示上传到 Bucket 内的 Object 的完整路径,例如 exampledir/exampleobject.txtObject,完整路径中不能包含 Bucket 名称。
   // filename 表示待上传的本地文件名称。
   'key' : key + '${filename}',
   'policy': UploadParams.policy,
   'OSSAccessKeyId': UploadParams.accessid,
   // 设置服务端返回状态码为200,不设置则默认返回状态码204。
   'success_action_status' : '200',    
   'signature': UploadParams.signature,
}
let requestData = new FormData();

Object.keys(params).map(key => {
  requestData.Append(key, params[key]);
});
// 获取的上传 file 文件,file 必须为最后一个表单域,除 file 以外的其他表单域无顺序要求
requestData.append('file', fileObj);

// 非 form-data 类型(非阿里云云服务会遇到,以下代码仅举例,不代表真实使用场景)
let requestData = fileObj;
let headers = {
   'key' : key + '${filename}',
   'policy': UploadParams.policy,
   'OSSAccessKeyId': UploadParams.accessid,
   'success_action_status' : '200',    
   'signature': UploadParams.signature,
}

// 进行接口请求,上传文件
axIOS({
  method: 'post',
  url: params.host,
  data: requestData,
  headers: headers || {},
});

这里代码只是简单的示例,实际使用时需要对各个文件服务需要进行不同的适配。

加密算法和解析

对于获取 Signature 鉴权信息等内容时,后端服务在有文档或者 SDK 时,可以对接不同的云服务 JAVA SDK 直接进行生成临时授权的信息,在没有文档的情况下,则需要前端或者后端,针对各个不同的云服务,进行解析加密 Signature 的步骤(我司这里是前端进行了加密过程解析后,后续日常生成由后端服务完成)。

加密算法

此处我以紫光云的 Signature 生成步骤给大家简单介绍下加密算法的流程,不同的云服务,加密过程都比较类似。

图片

图片来源:紫光云上传流程(https://www.unicloud.com/document/show-19262078.html)

以下是根据上述的加密流程写的测试生成 Signature 的代码部分,大家也可以自行测试试用。

按流程主要分成3步即可

  1. 生成 CanonicalRequest 字段
  2. 生成前面的 StringToSign
  3. 根据 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 格式时间

  const uriFileName = uriEscapePath(filename)
  const content = 'UNSIGNED-PAYLOAD'
  
  // 生成 CanonicalRequest 字段
  let CanonicalRequest = `PUTn${uriFileName}nncontent-disposition:attachment;filename=uploadTest.pngncontent-type:image/pngnhost:oos-cn.ctyunapi.cnnx-amz-content-sha256:${content}nx-amz-date:${timeStampISO8601Format}nncontent-disposition;content-type;host;x-amz-content-sha256;x-amz-daten${content}`
  let hashedCanonicalRequest = crypto.createHash('sha256').update(CanonicalRequest).digest('hex');

  // 生成前面的 StringToSign
  const signStr = `AWS4-Hmac-SHA256n${timeStampISO8601Format}n${dateString}/cn/s3/aws4_requestn${hashedCanonicalRequest}`
  //根据 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('


Tags:前端   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
20k级别前端是怎么使用LocalStorage的,想知道吗?
当咱们把咱们想缓存的东西,存在localStorage、sessionStorage中,在开发过程中,确实有利于咱们的开发,咱们想看的时候也是一目了然,点击Application就可以看到。前言大家好,我是林...【详细内容】
2024-03-26  Search: 前端  点击:(12)  评论:(0)  加入收藏
前端不存在了?盲测64%的人更喜欢GPT-4V的设计,杨笛一等团队新作
3 月 9 日央视的一档节目上,百度创始人、董事长兼 CEO 李彦宏指出,以后不会存在「程序员」这种职业了,因为只要会说话,人人都会具备程序员的能力。「未来的编程语言只会剩下两种...【详细内容】
2024-03-11  Search: 前端  点击:(9)  评论:(0)  加入收藏
前端开始“锈化”?Vue团队开源JS打包工具:基于Rust、速度极快、尤雨溪主导
Vue 团队已正式开源Rolldown &mdash;&mdash; 基于 Rust 的 JavaScrip 打包工具。Rolldown 是使用 Rust 开发的 Rollup 替代品,它提供与 Rollup 兼容的应用程序接口和插件接口...【详细内容】
2024-03-09  Search: 前端  点击:(11)  评论:(0)  加入收藏
两年前端经验还不会手写Promise?
什么是promise?当我们处理异步操作时,我们经常需要进行一系列的操作,如请求数据、处理数据、渲染UI等。在过去,这些操作通常通过回调函数来处理,但是回调函数嵌套过多会导致代码...【详细内容】
2024-03-07  Search: 前端  点击:(23)  评论:(0)  加入收藏
十个前端冷门但好用的前端工具函数库
本文推荐十个冷门但好用的前端工具函数仓库,它们可能没有很高的知名度,但却能为你解决实际问题,提高开发效率。在前端开发中,有时候我们会遇到一些常见的功能需求,但却不知道从哪...【详细内容】
2024-02-27  Search: 前端  点击:(21)  评论:(0)  加入收藏
前端开发:Visual Studio Code和Visual studio如何选?
Visual Studio Code和Visual studio都是微软的集成开发环境(IDE),那么在实际工作中该如何选择呢。贝格前端工场对二者做一番对比,帮助您决策一下。一、Visual Studio Code的介绍...【详细内容】
2024-02-27  Search: 前端  点击:(46)  评论:(0)  加入收藏
网站开发中的前端和后端开发有什么区别
前端开发和后端开发都是干什么的?有哪些区别?通俗地讲,前端干的工作是用户可以直接看得见的,而后端开发的工作主要在服务端,用户不太能直接看到。虽然前端开发和后端开发的工作有...【详细内容】
2024-02-21  Search: 前端  点击:(32)  评论:(0)  加入收藏
一段微信小程序前端与后端连接的代码,带注解
微信小程序的前端和后端连接通常涉及到使用微信小程序提供的网络请求API与后端服务器进行通信。以下是一个简单的示例,展示如何使用微信小程序的前端代码向后端发送请求并处...【详细内容】
2024-01-24  Search: 前端  点击:(55)  评论:(0)  加入收藏
如何优雅的实现前端国际化?
JavaScript 中每个常见问题都有许多成熟的解决方案。当然,国际化 (i18n) 也不例外,有很多成熟的 JavaScript i18n 库可供选择,下面就来分享一些热门的前端国际化库!i18nexti18ne...【详细内容】
2024-01-17  Search: 前端  点击:(69)  评论:(0)  加入收藏
JavaScript前端框架2024年展望
Angular、Next.js、React和Solid的维护者和创作者们展望2024年,分享了他们计划中的改进。译自2024 Predictions by JavaScript Frontend Framework Maintainers,作者 Loraine...【详细内容】
2024-01-05  Search: 前端  点击:(91)  评论:(0)  加入收藏
▌简易百科推荐
20k级别前端是怎么使用LocalStorage的,想知道吗?
当咱们把咱们想缓存的东西,存在localStorage、sessionStorage中,在开发过程中,确实有利于咱们的开发,咱们想看的时候也是一目了然,点击Application就可以看到。前言大家好,我是林...【详细内容】
2024-03-26  前端之神  微信公众号  Tags:前端   点击:(12)  评论:(0)  加入收藏
前端不存在了?盲测64%的人更喜欢GPT-4V的设计,杨笛一等团队新作
3 月 9 日央视的一档节目上,百度创始人、董事长兼 CEO 李彦宏指出,以后不会存在「程序员」这种职业了,因为只要会说话,人人都会具备程序员的能力。「未来的编程语言只会剩下两种...【详细内容】
2024-03-11  机器之心Pro    Tags:前端   点击:(9)  评论:(0)  加入收藏
前端开始“锈化”?Vue团队开源JS打包工具:基于Rust、速度极快、尤雨溪主导
Vue 团队已正式开源Rolldown &mdash;&mdash; 基于 Rust 的 JavaScrip 打包工具。Rolldown 是使用 Rust 开发的 Rollup 替代品,它提供与 Rollup 兼容的应用程序接口和插件接口...【详细内容】
2024-03-09  OSC开源社区    Tags:Vue   点击:(11)  评论:(0)  加入收藏
两年前端经验还不会手写Promise?
什么是promise?当我们处理异步操作时,我们经常需要进行一系列的操作,如请求数据、处理数据、渲染UI等。在过去,这些操作通常通过回调函数来处理,但是回调函数嵌套过多会导致代码...【详细内容】
2024-03-07  海燕技术栈  微信公众号  Tags:Promise   点击:(23)  评论:(0)  加入收藏
网站开发中的前端和后端开发有什么区别
前端开发和后端开发都是干什么的?有哪些区别?通俗地讲,前端干的工作是用户可以直接看得见的,而后端开发的工作主要在服务端,用户不太能直接看到。虽然前端开发和后端开发的工作有...【详细内容】
2024-02-21  CarryData    Tags:前端   点击:(32)  评论:(0)  加入收藏
网站程序开发中的前后端分离技术
随着互联网的快速发展和技术的不断创新,传统的网站开发模式已经难以满足日益增长的业务需求。为了提高开发效率、增强系统的可维护性和可扩展性,前后端分离技术逐渐成为了网站...【详细内容】
2024-01-31  网站建设派迪星航    Tags:前后端分离   点击:(23)  评论:(0)  加入收藏
如何优雅的实现前端国际化?
JavaScript 中每个常见问题都有许多成熟的解决方案。当然,国际化 (i18n) 也不例外,有很多成熟的 JavaScript i18n 库可供选择,下面就来分享一些热门的前端国际化库!i18nexti18ne...【详细内容】
2024-01-17  前端充电宝  微信公众号  Tags:前端   点击:(69)  评论:(0)  加入收藏
Vue中Scope是怎么做样式隔离的?
scope样式隔离在 Vue 中,样式隔离是通过 scoped 特性实现的。当在一个组件的 <style> 标签上添加 scoped 特性时,Vue 会自动为这个样式块中的所有选择器添加一个唯一的属性,以...【详细内容】
2024-01-04  海燕技术栈  微信公众号  Tags:Vue   点击:(80)  评论:(0)  加入收藏
vue3中 ref和 reactive的区别 ?
最近有朋友在面试过程中经常被问到这么一个问题,vue3 中的ref 和 reactive的区别在哪里,为什么 要定义两个API 一个 api不能实现 响应式更新吗??带着这个疑问 ,我们 接下来进行逐...【详细内容】
2024-01-03  互联网高级架构师  今日头条  Tags:vue3   点击:(38)  评论:(0)  加入收藏
React18 与 Vue3 全方面对比
1. 编程风格 & 视图风格1.1 编程风格 React 语法少、难度大;Vue 语法多,难度小例如指令:Vue<input v-model="username"/><ul> <li v-for="(item,index) in list" :key="inde...【详细内容】
2024-01-03  爱做梦的程序员  今日头条  Tags:Vue3   点击:(72)  评论:(0)  加入收藏
站内最新
站内热门
站内头条