基于ali-oss实现不同类型文件上传不同的bucket

基于ali-oss实现不同类型文件上传不同的bucket,并根据大小选择直接上传还是分片上传

  • 1 配置OSS
  • 2 引入依赖
  • 3 上传核心代码
  • 4 文件回显

1 配置OSS

可以看阿里云文档
ps:记得配置跨域

2 引入依赖

pnpm install ali-oss -save

3 上传核心代码

import OSS from "ali-oss";
import dayjs from "dayjs"; // 引入时间组件
import { buildUUID } from "@pureadmin/utils";
import { getStsToken } from "@/api/common/oss";
const BUCKET_PREFIX = "XXX";
// 获取不同文件类型bucket
const OSS_BUCKET_OBJECT = {
  image: BUCKET_PREFIX + "-image",
  audio: BUCKET_PREFIX + "-audio",
  video: BUCKET_PREFIX + "-video1",
  application: BUCKET_PREFIX + "-file",
  other: BUCKET_PREFIX + "-upload"
};
// 分片的大小
const SHARD_SIZE = 5;
// 文件大小阈值,主要区分直接上传和分片上传
const FILE_SIZE_THRESHOLD = 50;
type configType = {
  accessKeyId: string;
  accessKeySecret: string;
  bucket: string;
  expiration: string;
  region: string;
  token: string;
  stsToken: string;
};
let config: configType = undefined;
// 对文件进行上传
export async function uploadFile(file, progressCallback = () => {}) {
  // progressCallback 三个参数 (进度, 断点信息, 返回值)
  // 校验传入的对象是否正确
  if (!file || Object.prototype.toString.call(file) !== "[object File]") {
    throw new Error("参数不正确");
  }
  // 根据约定和相关规则进行参数配置
  const ossConfig: configType = await getOssConfig();
  ossConfig.bucket = getBucket(file);
  ossConfig.stsToken = ossConfig.token;
  const environment = `/${import.meta.env.VITE_LOGOGRAM}`;
  const pathName = `${environment}/${dayjs().format("YYYY-MM-DD")}/`;
  const fileName = `${buildUUID()}.${file.name.split(".").at(-1)}`;
  // 实例化OSS对象
  const client = new OSS(ossConfig);
  try {
    const fileSize = file.size / 1024 / 1024;
    // 根据文件大小选择上传的方式
    if (fileSize > FILE_SIZE_THRESHOLD) {
      const option = {
        partSize: 1024 * 1024 * SHARD_SIZE,
        parallel: Math.ceil(fileSize / SHARD_SIZE),
        progress: progressCallback
      };
      const result = await client.multipartUpload(
        pathName + fileName,
        file,
        option
      );
      return `/${result.name}`;
    } else {
      const result = await client.put(pathName + fileName, file);
      return `/${result.name}`;
    }
  } catch (e) {
    return Promise.reject(e);
  }
}

// 获取后端返回的临时凭证,并根据时间判断凭证是否过期
export async function getOssConfig() {
  if (config?.expiration && dayjs().isBefore(dayjs(config.expiration))) {
    return config;
  } else {
    const { data } = await getStsToken();
    config = data as configType;
    return data;
  }
}

// 根据文件类型获取不同的bucket
function getBucket(file) {
  const bucket = OSS_BUCKET_OBJECT[file.type.split("/")[0]];
  if (bucket) return bucket;
  else return OSS_BUCKET_OBJECT["other"];
}


4 文件回显

// 访问协议
const AGREEMENT = "https://";
// 获取不同文件类型的访问地址
const SERVER_ADDRESS = {
  image: "img.xxx.xxx.com",
  audio: "audio.xxx.xxx.com",
  video: "video.xxx.xxx.com",
  application: "file.xxx.xxx.com",
  other: "upload.xxx.xxx.com"
};
export const imageRegex = RegExp(/(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)/);
export const audioRegex = RegExp(/(mp3|wav|flac|ogg|aac|wma)/);
export const videoRegex = RegExp(
  /(avi|wmv|mpeg|mp4|m4v|mov|asf|flv|f4v|rmvb|rm|3gp|vob)/
);
export const applicationRegex = RegExp(
  /(doc|docx|xls|xlsx|ppt|pptx|pdf|txt|apk|zip)/
);
export function preview(pathName) {
  const suffix = pathName.split(".").at(-1);
  let type = "other";
  if (imageRegex.test(suffix)) type = "image";
  if (audioRegex.test(suffix)) type = "audio";
  if (videoRegex.test(suffix)) type = "video";
  if (applicationRegex.test(suffix)) type = "application";
  return `${AGREEMENT}${SERVER_ADDRESS[type]}${pathName}`;
}
deoRegex.test(suffix)) type = "video";
  if (applicationRegex.test(suffix)) type = "application";
  return `${AGREEMENT}${SERVER_ADDRESS[type]}${pathName}`;
}

你可能感兴趣的:(javascript,前端)