阿里云oss上传(使用element vue3)

2,240 阅读1分钟

先贴代码

<template>
  <el-row>
    <el-col :span="24" p-t-20px>
      <el-upload
        action
        ref="uploadBtn0"
        multiple
        :limit="3"
        :on-exceed="handleExceed"
        :on-success="handleUploadSuccess"
        :file-list="FileList"
        :on-change="handleChange"
        :on-remove="handleRemove"
        :auto-upload="false"
      >
        <el-button size="small" type="primary">点击上传</el-button>
        <template #tip>
          <div class="el-upload__tip">只能上传 jpg/png 文件,且不超过 500kb</div>
        </template>
      </el-upload>
    </el-col>
    <el-col :span="0" p-t-20px>
      <el-button
        v-show="true"
        style="margin-left: 10px"
        size="small"
        type="success"
        @click="multipartUpload"
        ref="uploadBtn"
      >上传到服务器</el-button>
      <el-button
        style="margin-left: 10px"
        size="small"
        type="success"
        @click="resumeUpload"
      >继续</el-button>
      <el-button
        style="margin-left: 10px"
        size="small"
        type="success"
        @click="stopUplosd"
      >暂停</el-button>
    </el-col>
  </el-row>
  <el-progress :percentage="percentage" :status="uploadStatus"></el-progress>
</template>

<script setup lang="ts">
import { ref, reactive, inject, onMounted, computed, watch } from 'vue'
import OSS from "ali-oss";
import { post } from "@/js/ajaxFn"
import { ElMessage } from 'element-plus'
const FileList = ref([])
let file = null
const tempCheckpoint = ref(null) // 用来缓存当前切片内容
const uploadId = ref('')
const uploadStatus = ref(null) // 进度条上传状态
const percentage = ref(0) // 进度条百分比
const uploadName = ref('') //Object所在Bucket的完整路径

const props = defineProps([
  "handleExceed",
  "handleUploadSuccess",
  "fileList",
  "prePath",
  "fileTypeList",
  "fileSize",
])

const uploadBtn0 = ref(null)
const uploadBtn = ref(null)

// 上传文件前限制文件格式
async function limitFileType(file:any) { 
  const { fileTypeList } = props
  let type = file.name.substring(file.name.lastIndexOf('.') + 1)
  // 不传这个参数表示可以传任何类型的文件
  if(!fileTypeList) return true
  if(fileTypeList.includes(type)) return true
  await ElMessage.error(`${type}类型文件禁止上传`)
  return false
}

// 上传文件前限制文件大小
async function limitFileSize(file:any) {
  const { fileSize } = props
  let size = Number(file.size)
  // 不传这个参数表示不限制文件大小
  if(!fileSize) return true
  if(fileSize > size) return true
  let info = fileSize >= 1024 ? `${Number((fileSize / 1024).toFixed())}M` : `${fileSize}KB`
  await ElMessage.error(`文件超过了${info}`)
  return false
}

// 恢复上传
async function resumeUpload() {
  window.removeEventListener("online", resumeUpload);
  if (!tempCheckpoint.value) {
    ElMessage.error("请先上传");
    return;
  }
  uploadStatus.value = null;
  try {
    let result = await client.multipartUpload(file.name, file, {
      progress: (p, checkpoint) => {
        percentage.value = p * 100;
        console.log(
          p,
          checkpoint,
          "checkpoint----恢复上传的切片信息-------"
        );
        tempCheckpoint.value = checkpoint;
      },
      checkpoint: tempCheckpoint,
      meta: { year: 2022, people: "test" },
      // mime: file.type,
    });
    console.log(result, "result-=-=-恢复上传完毕");
  } catch (e) {
    console.log(e, "e-=-=-");
  }
}

async function abortMultipartUpload() {
  window.removeEventListener("online", resumeUpload);
  const name = uploadName; // Object所在Bucket的完整路径。
  // const uploadId = upload; // 分片上传uploadId。
  const result = await client.abortMultipartUpload(name, uploadId.value);
  console.log(result, "=======清除切片====");
}
// 暂停分片上传。
function stopUplosd() {
  window.removeEventListener("online", resumeUpload); // 暂停时清除时间监听
  let result = client.cancel();
  console.log(result, "---------暂停上传-----------");
}
// 切片上传
async function multipartUpload() {
  if (!props.prePath) {
    ElMessage.error("请选择作品要求");
    return;
  }
  if (!file) {
    ElMessage.error("请选择文件");
    return;
  }
  if(!(await limitFileType(file))) return
  if(!(await limitFileSize(file))) return
  uploadStatus.value = null;
  // console.log("uploadStatus",file, uploadStatus);
  percentage.value = 0;
  try {
    //object-name可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
    const fullPath = props.prePath + file.name
    let result = await client
      .multipartUpload(fullPath, file, {
        headers: {
          "Content-Disposition": "inline",
          // "Content-Type": file.type, //注意:根据图片或者文件的后缀来设置,我试验用的‘.png'的图片,具体为什么下文解释
        },
        progress: (p, checkpoint) => {
          tempCheckpoint.value = checkpoint;
          uploadId.value = checkpoint && checkpoint.uploadId;
          uploadName.value = checkpoint && checkpoint.name;
          percentage.value = (p * 100).toFixed(2);
          console.log(
            p,
            checkpoint,
            percentage,
            "---------uploadId-----------"
          );
          // 断点记录点。浏览器重启后无法直接继续上传,您需要手动触发上传操作。
        },
        // meta: { year: 2020, people: "dev" },
        // mime: file.type,
      })
      .then((res:any) => {
        props.handleUploadSuccess(res)
        console.log(res, "完成了");
      },
      (err:any) => {
        console.log(err, '错误原因');
        // ElMessage.error('')
      }
      );
    console.log(result, percentage, "result= 切片上传完毕=");
  } catch (e) {
    console.log(e, '这里是发生了错误');
    window.addEventListener("online", resumeUpload); // 该监听放在断网的异常处理
    // 捕获超时异常。
    if (e.code === "ConnectionTimeoutError") {
      // 请求超时异常处理
      uploadStatus.value = "exception";
      console.log("TimeoutError");
      // do ConnectionTimeoutError operation
    }
    // console.log(e)
  }
}

// 选择文件发生改变
function handleChange(theFile, FileList) {
  FileList = FileList.filter((row) => row.uid == theFile.uid);
  file = theFile.raw;
  console.log(file, FileList);
  // 文件改变时上传
  // submitForm(file)
  uploadBtn.value.$el.click();
}

function handleRemove(file, FileList) {
  percentage.value = 0; //进度条置空
  FileList = [];
}

let client;
function initOss() {
  let params = {};
  let token = localStorage.getItem("mytoken");
  post("/ajax/public/oss/get_sts_token", params, (res) => {
    const { AccessKeyId, AccessKeySecret, Expiration, SecurityToken } = res;
    client = new OSS({
      region: "oss-cn-shanghai", //根据那你的Bucket地点来填写
      accessKeyId: AccessKeyId, //自己账户的accessKeyId
      accessKeySecret: AccessKeySecret, //自己账户的accessKeySecret
      stsToken: SecurityToken,
      bucket: "pro-dsbactc-prod-10001-oss", //bucket名字
      Expiration: Expiration,
      secure: true, // 上传链接返回支持https
    });
  });
}
initOss();
</script>

<script lang="ts">


export default {

  data() {
    return {
      // FileList: this.fileList,
      // file: null,
      // tempCheckpoint: null, // 用来缓存当前切片内容
      // uploadId: "",
      // uploadStatus: null, // 进度条上传状态
      // percentage: 0, // 进度条百分比
      // uploadName: "", //Object所在Bucket的完整路径
    };
  },
  methods: {
    // 取消分片上传事件

  },
};
</script>

第一步是初始化oss

  • 这里采用的是SDK的方式,npm i ali-oss, 然后去初始化
function initOss() {
  let params = {};
  let token = localStorage.getItem("mytoken");
  post("/ajax/public/oss/get_sts_token", params, (res) => {
    const { AccessKeyId, AccessKeySecret, Expiration, SecurityToken } = res;
    client = new OSS({
      region: "oss-cn-shanghai", //根据那你的Bucket地点来填写
      accessKeyId: AccessKeyId, //自己账户的accessKeyId
      accessKeySecret: AccessKeySecret, //自己账户的accessKeySecret
      stsToken: SecurityToken,
      bucket: "pro-dsbactc-prod-10001-oss", //bucket名字
      Expiration: Expiration,
      secure: true, // 上传链接返回支持https
    });
  });
}

第二步是去调用上传的方法

  • 上传分成两种方式,一种是简单上传,这种的话,就不能够去查看上传进度
  • 第二种的话是切片上传,这种的话,就可以拿到当前的上传进度,来用进度条了
  try {
    //object-name可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
    const fullPath = props.prePath + file.name
    let result = await client
      .multipartUpload(fullPath, file, {
        headers: {
          "Content-Disposition": "inline",
          // "Content-Type": file.type, //注意:根据图片或者文件的后缀来设置,我试验用的‘.png'的图片,具体为什么下文解释
        },
        progress: (p, checkpoint) => {
          tempCheckpoint.value = checkpoint;
          uploadId.value = checkpoint && checkpoint.uploadId;
          uploadName.value = checkpoint && checkpoint.name;
          percentage.value = (p * 100).toFixed(2);
          console.log(
            p,
            checkpoint,
            percentage,
            "---------uploadId-----------"
          );
          // 断点记录点。浏览器重启后无法直接继续上传,您需要手动触发上传操作。
        },
        // meta: { year: 2020, people: "dev" },
        // mime: file.type,
      })
      .then((res:any) => {
        props.handleUploadSuccess(res)
        console.log(res, "完成了");
      },
      (err:any) => {
        console.log(err, '错误原因');
        // ElMessage.error('')
      }
      );
    console.log(result, percentage, "result= 切片上传完毕=");
  } catch (e) {
    console.log(e, '这里是发生了错误');
    window.addEventListener("online", resumeUpload); // 该监听放在断网的异常处理
    // 捕获超时异常。
    if (e.code === "ConnectionTimeoutError") {
      // 请求超时异常处理
      uploadStatus.value = "exception";
      console.log("TimeoutError");
      // do ConnectionTimeoutError operation
    }
    // console.log(e)
  }