配合vant组件库封装一个uploader上传文件照片

 组件代码:

<template>
  <div>
    <Uploader
      :multiple="multiple"
      :max-count="maxCount"
      :preview-size="previewSize"
      v-model="fileList"
      accept="image/*"
      @click-upload="(e) => handleUpload(e)"
      @delete="deleteFile"
    ></Uploader>
  </div>
</template>

<script setup lang="ts">
import { Toast, Uploader } from 'vant';
import { ref, watch } from 'vue';

import { uploadImage } from '@/service/qualityInspectionOperations.ts';
import { dataURLtoFile } from './util.ts';

const emits = defineEmits(['changeUrl']);
const props = defineProps({
  multiple: {
    type: Boolean,
    default: false,
  },
  previewSize: {
    type: Number,
    default: 76,
  },
  maxSize: {
    type: Number,
    default: 1024,
  },
  maxCount: {
    type: Number,
    default: 1,
  },
  needCompressd: {
    type: Boolean,
    default: false,
  },
});

const fileList = ref([]);
const imgUrlList = ref([]);

const getBase64 = (filePath: string): Promise<string> => {
  return new Promise((resolve) => {
    const options = {
      filePath,
      format: 'base64',
    };
    // eslint-disable-next-line no-undef
    const base64Url = jme.file.getFileData(options);
    resolve(base64Url);
  });
};

const onUpload = async (file: Record<string, any>) => {
  const formData = new FormData();
  formData.append('file', file.file);
  const res = await uploadImage(formData);
  if (res.success && res.data) {
    fileList.value.push(file);
    imgUrlList.value.push(res.data);
  } else {
    Toast('上传失败');
  }
};

// 获取base64 调用上传
const getFileUrl = async (fileData) => {
  const fileName = fileData.name;
  const base64: string = await getBase64(fileData.path);
  const file = dataURLtoFile(base64, fileName);
  onUpload({ file, name: fileName, content: base64 });
};

const chooseFile = () => {
  const options = {
    count: props.maxCount,
    type: 'image',
    callback: (res: Record<string, any>[]) => {
      if (res?.length) {
        res.forEach((item) => {
          getFileUrl(item);
        });
      }
    },
  };
  // eslint-disable-next-line no-undef
  jme.file.chooseFile(options);
};

const handleUpload = (e) => {
  e.preventDefault();
  chooseFile();
};

const deleteFile = (_, { index }: { index: number }) => {
  imgUrlList.value.splice(index, 1);
};

watch(
  () => imgUrlList.value,
  (newVal) => {
    emits('changeUrl', newVal);
  },
  { deep: true }
);
</script>
<style lang="less" scoped>
:deep(.van-uploader__preview-delete--shadow) {
  width: 18px;
  height: 18px;
  border-radius: 0 0 0 18px;
}
:deep(.van-uploader__preview-delete-icon) {
  font-size: 16px;
}
</style>

utils代码:

/**
 * 将base64转换为Blob
 * @param {string} base64 - base64字符串
 * @return {Blob} Blob对象
 */
export function dataURItoBlob(dataURI: string) {
  const byteString = atob(dataURI.split(',')[1]);
  const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);
  // eslint-disable-next-line no-plusplus
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ab], { type: mimeString });
}

/**
 * 使用FormData将图片的base64字符串转换成File对象
 * @param {string} base64 - base64字符串
 * @param {string} filename - 文件名
 * @return {File} file对象
 */
export function dataURLtoFileWithFormData(base64: string, filename: string) {
  const formData = new FormData();
  formData.append('file', dataURItoBlob(base64), filename);
  return formData.get('file');
}

/**
 * 将图片的base64字符串转换成File对象
 * @param {string} base64 - base64字符串
 * @param {string} filename - 文件名
 * @return {File} file对象
 */
export function dataURLtoFile(base64: string, filename: string) {
  const arr = base64.split(',');
  const typeMatch = arr[0].match(/:(.*?);/);
  const mime = typeMatch[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  // eslint-disable-next-line no-plusplus
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime });
}

vant Uploader 是 Vue.js 中的一个轻量级文件上传组件,它隶属于 Vant 这个UI设计框架的一部分。Vant Uploader 提供了一个简单易用的API,用于处理用户选择文件、上传进度跟踪以及错误处理等功能。主要特点包括: 1. **拖放支持**:允许用户通过鼠标或触摸直接拖拽文件到指定区域进行上传。 2. **多选文件**:可以一次性选择多个文件,支持单选或多选模式。 3. **断点续传**:如果上传中断,可以保存部分上传的数据,在连接恢复后继续从上次断开的地方开始上传。 4. **进度条显示**:实时显示当前上传进度,让用户清楚了解上传状态。 5. **配置回调**:提供事件处理器,如 `before-upload`、`uploading`、`success` 和 `error` 等,可以根据需要自定义上传行为。 在使用 Vant Uploader 时,通常会先安装,然后在 Vue 组件模板或 methods 中初始化并绑定事件。例如: ```html <template> <van-uploader v-model="fileList" :before-upload="beforeUpload" @change="handleFileChange"> <div slot="tip">点击或拖拽文件至此</div> </van-uploader> </template> <script> import { Uploader } from 'vant'; export default { components: { VanUploader: Uploader, }, data() { return { fileList: [], }; }, methods: { beforeUpload(file) { // 在这里可以对文件进行预处理,如检查大小、格式等 if (/* 文件检查条件 */) { return true; } return false; }, handleFileChange(newFiles) { this.fileList = newFiles; // 更新文件列表 }, }, }; </script> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值