H5+Vant实现上传文件到阿里云OSS

313 阅读1分钟
  1. 使用van-uploader组件上传文件
   <van-uploader v-model="fileList" :after-read="(file) => afterRead(file, '2')" :before-read="beforeRead"
                :max-count="10" :preview-size="80" @delete="(file, detail) => deleteImg(file, detail, '2')" />
  1. 若文件需要压缩,则可在befor-read方法中处理文件格式
    beforeRead(file) {
      return new Promise((resolve) => {
        const fileName = file.name;
        Toast.loading({
          message: "图片压缩中...",
          duration: 0,
          forbidClick: true,
        });
        // 压缩图片
        compressAccurately(file, {
          size: 500,
          accuracy: 0.9,
          type: "image/jpeg",
        })
          .then((res) => {
            Toast.clear();
            // 注意: oss只支持File类型,压缩之后的文件为Bolb类型,此时需要转换文件类型
              const Files = new File([res], file.name, { type: file.type });
              resolve(Files);
          })
          .catch(() => {
            this.$notify({ type: "warning", message: "上传图片失败" });
          });
      });
    },
  1. after-read中进行上传oss文件操作
    async afterRead(file, type) {
      Toast.loading({
        message: "上传中...",
        forbidClick: true,
        duration: 0, // 持续展示 toast
      });
      const result = await this.$UploadOssFile(file.file)
      if (result.url) {
        // result.url为上传成功oss返回的文件url
        let imgUrl = result.url;
        // 这里写上传成功的代码....
        Toast.clear();
        this.$notify({ type: "success", message: "上传成功" });
      } else {
        Toast.clear();
        this.$notify({ type: "warning", message: "上传失败,请联系管理员!" });
      }
    },
  1. $UploadOssFile是我封装的关于上传oss的方法,可以在当前页面中引入,也可以在main.js中全局引入
    import { uploadFile } from "@/utils/oss";
    Vue.prototype.$UploadOssFile=uploadFile
  1. oss.js
import { api } from "@api";
import OSS from "ali-oss";
import moment from "moment";
// 随机生成uid,防止文件名重复
function getFileNameUUID() {
  function rx() {
    return (((1 + Math.random()) * 0x1000000) | 0).toString(16).substring(1);
  }
  return `${+new Date()}_${rx()}${rx()}`;
}
// 获取ossToken
function getOSSToken() {
  return api.getAlibabaStsToken().then((res) => res.data.data);
}
/**
 * 判断临时凭证是否到期。
 **/
function isCredentialsExpired(credentials) {
  if (!credentials) {
    return true;
  }
  const expireDate = new Date(credentials.expiration);
  const now = new Date();
  // 如果有效期不足一分钟,视为过期。
  return expireDate.getTime() - now.getTime() <= 60000;
}
async function uploadFile(file) {
  let credentials = JSON.parse(window.localStorage.getItem("credentials"));
  if (!file) return;
  if (isCredentialsExpired(credentials)) {
    credentials = await getOSSToken();
    window.localStorage.setItem("credentials", JSON.stringify(credentials));
  }
  // 配置OSS客户端
  const client = new OSS({
    region: "你的region",
    bucket: "你的bucket",
    expiration: credentials.expiration,
    accessKeyId: credentials.accessKeyId,
    accessKeySecret: credentials.accessKeySecret,
    stsToken: credentials.securityToken,
  });
  let uid = getFileNameUUID();
  let nowData = moment().format("yyyy/MM/DD");
  const result = await client
    .put(`${nowData}/${uid}_${file.name}`, file, {
      headers: {
        "Cache-Control": "max-age=2592000", //开启本地缓存,根据业务实际需要添加
      },
    })
    .then((res) => res)
    .catch((error) => error);
  return result;
}
export { isCredentialsExpired, uploadFile };