由于函数网关的问题,文件无法直传至函数,但我们也提供了两种方式来解决文件上传的问题。

【推荐】后端生成加密地址,前端上传

OSS 上传目前采用阿里云提供的开源包「ali-oss」,npm包地址:https://www.npmjs.com/package/ali-oss

安装

安装依赖

  1. npm i ali-oss -S && npm i @types/ali-oss -D

阿里云 OSS 配置

客户端进行表单直传到OSS时,会从浏览器向OSS发送带有Origin的请求消息。OSS对带有Origin头的请求消息会进行跨域规则(CORS)的验证,因此需要为Bucket设置跨域规则以支持Post方法

  1. 登录OSS管理控制台
  2. 单击Bucket列表,之后单击目标Bucket名称。
  3. 单击权限管理 > 跨域设置,在跨域设置区域单击设置
  4. 单击创建规则,配置如下图所示。

OSS 文件上传 - 图1

后端代码

  1. // src/apis/lambda/index.ts
  2. /**
  3. *
  4. * @param params Object {filename: 编码后文件名称}
  5. */
  6. export async function getOSSUploadUrl(params: { filename: string }) {
  7. const { filename } = params;
  8. const dir = 'user-dir-prefix/'; // OSS 文件根目录
  9. const client = new OSS({
  10. region: '<oss region>', // 这里需要修改成你自己的 region
  11. accessKeyId: '<Your accessKeyId>',// 这里需要修改成你自己的 accessKeyId
  12. accessKeySecret: '<Your accessKeySecret>', // 这里需要修改成你自己的 accessKeySecret
  13. bucket: '<Your bucket name>', // 这里需要修改成你自己的 bucket
  14. secure: true,
  15. });
  16. const url = client.signatureUrl(dir + decodeURIComponent(filename), {
  17. method: 'PUT',
  18. 'Content-Type': 'application/octet-stream',
  19. });
  20. return url;
  21. }

前端代码

  1. import React, { useEffect, useState } from 'react';
  2. import { getOSSUploadUrl } from '../../apis/lambda';
  3. export default () => {
  4. const [message, setMessage] = useState('');
  5. useEffect(() => {}, []);
  6. const uploadPhoto = (e: any) => {
  7. const file = e.target.files[0];
  8. const filename = encodeURIComponent(file.name);
  9. getOSSUploadUrl({ filename }).then((url) => {
  10. const contentType = 'application/octet-stream';
  11. const body = new Blob([file], { type: contentType });
  12. fetch(url, {
  13. method: 'PUT',
  14. headers: new Headers({ 'Content-Type': contentType }),
  15. body,
  16. })
  17. .then((res) => {
  18. setMessage(`上传成功!文件路径:${url.substring(0, url.indexOf('?'))}`);
  19. })
  20. .catch((e) => {
  21. console.log(e);
  22. });
  23. });
  24. };
  25. return (
  26. <div className="common-container">
  27. <>
  28. <p>上传文件,可以在accept属性中控制想要传的文件类型</p>
  29. <input onChange={uploadPhoto} type="file" accept="*" />
  30. </>
  31. <p>{message}</p>
  32. </div>
  33. );
  34. };

注意事项

获取上传文件地址的时候有很多的权限设置可以在 阿里云的 OSS 控制台设置,如果返回的url在页面中打不开,那么需要在 OSS 控制台授权
image.png

前端 OSS SDK 直传

小文件(大小 < 3m)可通过编码至 base64 上传,大文件请采用前端 OSS 的方式上传。参考文档:OSS Browser.js SDK

前端 OSS SDK 可能会有泄露 access key 与 sercet key 的问题,推荐配合 阿里云临时安全令牌(Security Token Service,STS) 使用。