OSS 自定义上传,单文件支持上传进度

386 阅读1分钟

在OSS上传中实现自定义单文件上传进度

背景

在日常的开发中,使用阿里云对象存储服务(OSS)是一个常见需求。然而,阿里提供的 ali-oss SDK 不直接支持文件上传进度的显示(切片上传的进度是每个切片为单位,不是传统请求的上传进度)。对于需要实时反馈上传状态的场景,例如文件上传功能,开发者需要寻找替代方案。本文将展示如何通过自己生成签名实现使用 axios 自定义上传,支持单文件上传进度显示。

实现

通过实现 authorizationOss 方法,我们可以借助 axios 的事件钩子来自定义上传逻辑,并监听 onUploadProgress 事件以实现实时进度更新。

以下是实现代码:

// 定义请求头信息
const headers = {
  authorization: '',
  'Content-Type': file.type || 'application/octet-stream',
  'x-oss-date': date, // 当前时间
  'x-oss-user-agent': 'aliyun-sdk-js/6.17.1 Chrome 110.0.0.0 on Windows 10 64-bit',
};

// 生成 Authorization 信息
headers.authorization = authorizationOss('PUT', path, headers);

// 使用 axios 发起 PUT 请求上传文件
const res = await axios.put(url, file, {
  headers,
  ...config,
  onUploadProgress: (progressEvent) => {
    const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    console.log(`Upload Progress: ${percentCompleted}%`);
  },
});

/**
 * 生成 OSS 授权签名
 * @param {string} method - HTTP 请求方法,例如 PUT 或 GET
 * @param {string} path - OSS 中的文件路径
 * @param {Record<string, string>} headers - 请求头信息
 * @returns {string} OSS 授权签名
 */
export const authorizationOss = (
  method: string,
  path: string,
  headers: Record<string, string>
) => {
  if (!ossConfig) return '';
  const { accessKeyId, accessKeySecret, bucket } = ossConfig;

  // 签名规则,参考 OSS 文档
  const signature = Crypto.enc.Base64.stringify(
    Crypto.HmacSHA1(
      `${method.toUpperCase()}

${headers['Content-Type']}
${headers['x-oss-date']}
x-oss-date:${headers['x-oss-date']}
x-oss-user-agent:${headers['x-oss-user-agent']}
/${bucket}/${path}`,
      accessKeySecret
    )
  );

  return 'OSS ' + accessKeyId + ':' + signature;
};

注意

示例代码的 authorizationOss 方法是在客户端(浏览器端)实现的,实际上,通过服务端生成临时 Token 是更好的做法。