文件上传

63 阅读2分钟
  • xxx.ts
const BASE_URL = "xxx";

// 创建配置文件副本
const createReplica = async function (name: string) {
  const url = BASE_URL + `xx`;
  await axios.post(url);
};
// 查询文件列表
const getFileList = async function (name: string) {
  const url = BASE_URL + `xx`;
  const res = await axios.get(url);
  return res;
};
// 导入文件
const importFile = async function (name: string, file: FormData) {
  const url = BASE_URL + `xx`;
  const res: string[] = await axios.post(url, file, {
    headers: { "Content-Type": "multipart/form-data" },
  });
  return res;
};
// 导出文件
const exportFile = async function (name: string, fileName: string) {
  const url = BASE_URL + `xx`;
  const responseTypeJson: object = { responseType: "blob" };
  const res = await axios.get<Blob>(url, {}, responseTypeJson);
  return res;
};
// 删除文件
const deleteFile = async function (name: string, fileName: string) {
  const url = BASE_URL + `xx`;
  const res: string[] = await axios.del(url);
  return res;
};
// 确认导入
const confirmImport = async function (name: string) {
  const url = BASE_URL + `xx`;
  await axios.post(url);
};
// 取消导入
const cancelImport = async function (name: string) {
  const url = BASE_URL + `xx`;
  await axios.post(url);
};
export default {
  createReplica,
  getFileList,
  importFile,
  exportFile,
  deleteFile,
  confirmImport,
  cancelImport,
};
  • xxx.vue
<template>
  <div class="import-files">
    <span>名称:xxx</span>
    <div class="btn-save">
      <tiny-button type="primary" @click="saveFile">保存</tiny-button>
    </div>
    <tiny-file-upload
      ref="uploadRef"
      drag
      multiple
      :file-list="fileList"
      :max-name-length="200"
      :before-upload="uploadFile"
      :before-remove="deleteFile"
      @preview="downloadFile"
    >
      <tiny-icon-fileupload class="icon-fileupload" />
      <div class="tiny-upload_text">
        <em>点击或拖拽文件到此处上传</em>
        <div class="upload-tip">(上传格式支持:txt)</div>
      </div>
    </tiny-file-upload>
  </div>
</template>
<script lang="ts" setup>
import { ref, onMounted, toRaw } from "vue";
import {createReplica,getFileList,importFile,exportFile,deleteFile,confirmImport,cancelImport} from '@/apis'

const props = defineProps({
  name: {
    type: String,
    required: true,
  },
});
const emit=defineEmits<{
    (e:'back'):void
}>()
const uploadRef = ref();
const fileList = ref([]);
const downloadFileName = ref();
const isValidateFile = ref(true);
const deleteFileName = ref();
const uploadData = ref();
// 上传文件
const uploadFile = (file: any) => {
  uploadData.value = file;
  isValidateFile.value = false;
  // 文件类型
  const allowedTypes = ["txt"];
  if (!allowedTypes.includes(file.name.split(".")[1])) {
    Notify({
      type: "error",
      message: `上传文件失败:不支持.${file.name.split(".")[1]}格式`,
      position: "top-right",
    });
    return;
  }
  // 重复名称
  const fileTypes= Array.from(toRaw(fileList.value), ({ name }) => name);
  if (fileTypes.includes(file.name)) {
    Modal.confirm(
      `文件${file.name}已存在,您确定继续上传并覆盖原文件吗?`,
      "上传文件",
      confirmUpload
    );
    return;
  } else {
    confirmUpload();
  }
  return false;
};
const confirmUpload = async () => {
  const formDate = new FormData();
  formDate.append("file", uploadData.value);
  const res = await importFile(props.name, formDate);
  res && refreshFileList(res);
  Notify({
    type: "success",
    message: "上传文件成功",
    position: "top-right",
  });
  isValidateFile.value=true
};
// 下载文件
const downloadFile=(file:any)=>{
  downloadFileName.value=file.name
  Modal.confirm(
    `您确定下载${file.name}文件吗?`,
    "下载文件",
    confirmExportFile
  );
}
const confirmExportFile=async()=>{
  const res=await exportFile(props.name,downloadFileName.value)
  const blob=new Blob([res])
  const url=window.URL.createObjectURL(blob)
  const link=document.createElement('a')
  link.href=url
  link.download=downloadFileName.value
  link.click()
  URL.revokeObjectURL(url)
}
// 删除文件
const deleteFile=(file:any)=>{
  if(isValidateFile.value){
    deleteFileName.value=file.name
    Modal.confirm(
      `您确定删除${file.name}文件吗?`,
      "删除文件",
      confirmDeleteFile
    )
  return false
}
const confirmDeleteFile=async()=>{
  const res=await deleteFile(props.name,deleteFileName.value)
  Notify({
    type: "success",
    message: "删除文件成功",
    position: "top-right",
  });
  res&&refreshFileList(res)
}
const refreshFileList=(res:string[])=>{
  fileList.value=[]
  res.forEach(item=>{
    fileList.value.push({name:item} as object)
  })
}
// 确认导入
const saveFile=async()=>{
  await confirmImport(props.name)
  Notify({
    type: "success",
    message: "保存文件成功",
    position: "top-right",
  });
  emit('back')
}
// 取消导入
const backPage=()=>{
  Modal.confirm(
    '您确定取消配置文件导入吗',
    "取消导入",
    confirmCancel
  );
}
const confirmCancel=async()=>{
  await cancelImport(props.name)
  emit('back')
}
//创建配置文件副本
const createFileReplica=async()=>{
  await createReplica(props.name)
}
 // 查询文件列表
 const initFileList=async()=>{
  const res=await getFileList(props.name)
  if(res){
    fileList.value=[]
    res.forEach(item=>{
      fileList.value.push({name:item.fileName} as object)
    })
  }
 }
 onMounted(()=>{
  createFileReplica()
  initFileList()
 })
</script>
<style lang="scss" scoped>
.import-files{
    user-select: none;
    .btn-save{
        float: :right;
        margin-bottom: 10px;
    }
    .upload-tip{
        font-size: 12px;
        color:#ccc
    }
    :deep(.tiny-upload){
        width: 100%;
    }
    .tiny-button{
        height: 30px;
        min-width: 100px;
    }
    :deep(.tiny-upload-list__item){
        float: left;
        width: max-content;
    }
    :deep(.tiny-upload-list__item-name){
        overflow: visible !important;
        white-space: nowrap !important;
        text-overflow: clip !important;
    }
}
</style>