在前端开发中,文件上传和预览功能是常见的需求之一。本文将介绍如何利用 Ant Design Vue 组件库实现文件上传与预览功能。我们将使用 Ant Design Vue 中的 Upload 组件来实现文件上传,并结合 Modal 组件实现文件预览功能。
```
<template>
<a-upload
v-model:file-list="fileList" <!-- 将文件列表与组件双向绑定 -->
list-type="picture-card"
:action="uploadFileParams.url"
:headers="uploadFileParams.headers"
multiple
@preview="handlePreview"
@change="handleUploadChange">
<plus-outlined />
</a-upload>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
</template>
```
```
<script setup>
import { ref, reactive, computed } from "vue";
import type { , UploadChangeParam } from "ant-design-vue";
import { uploadFile } from "@/api/base.js";
const formState = reactive<any>({
fileList: computed(() => {//存储文件列表
return fileList.value
.filter((ele: any) => {
return ele.url;
})
.map((ele: any) => {
return ele.url;
});
}),
});
// 使用 ref 创建响应式数据,用于控制图片预览弹窗的可见性
const previewVisible = ref(false);
// 使用 ref 创建响应式数据,存储预览图片的地址
const previewImage = ref("");
// 使用 Vue 3 中的 reactive 创建响应式对象,存储上传文件的参数
const uploadFileParams = uploadFile //上传图片接口
// 处理文件上传改变时的回调函数
const handleUploadChange = ({ file }: UploadChangeParam) => {
// 检查文件是否上传完成
if (file.status === "done") {
// 遍历文件列表
fileList.value.forEach((ele: any) => {
// 如果文件已上传且URL不存在
if (ele.status === "done" && !ele.url) {
// 检查响应是否成功
if (ele.response.code === 0) {
// 将URL设置为响应中的数据
ele.url = ele.response.data;
} else {
// 若响应失败,则URL为空字符串
ele.url = "";
}
}
});
}
};
// 处理关闭预览弹窗的回调函数
const handleCancel = () => {
previewVisible.value = false; // 将预览弹窗设置为不可见
};
const isImageUrl = (url: any) => {
// 定义图片格式的正则表达式
const imgPattern = /.(jpeg|jpg|gif|png|bmp)$/i;
// 检查 URL 结尾是否匹配图片格式
const endsWithImageFormat = imgPattern.test(url);
// 检查 URL 开头是否是 http:// 或 https://
const startsWithHttp = url.startsWith("http://") || url.startsWith("https://");
// 如果 URL 结尾匹配图片格式并且开头是 http:// 或 https://,则返回 true,否则返回 false
return endsWithImageFormat && startsWithHttp;
};
// 将文件转换为 Base64 格式的函数
// 定义一个函数 getBase64,接受一个文件对象作为参数
const getBase64 = (file) => {
// 返回一个 Promise 对象,用于处理异步操作
return new Promise((resolve, reject) => {
// 创建一个 FileReader 对象
const reader = new FileReader();
// 调用 readAsDataURL 方法,读取文件内容,并以 Data URL 的形式返回
reader.readAsDataURL(file);
// 读取完成后的回调函数
reader.onload = () => resolve(reader.result); // 使用 resolve 将结果传递给 Promise 的 then 方法
// 读取出错时的回调函数
reader.onerror = (error) => reject(error); // 使用 reject 将错误传递给 Promise 的 catch 方法
});
};
// 图片
const handlePreview = async (file: any) => {
if (file.fileType == "png" || isImageUrl(file.url)) {
if (!file.url && !file.preview) {
file.preview = (await getBase64(file.originFileObj)) as string;
}
previewImage.value = file.url || file.preview;
previewVisible.value = true;
} else {
window.location.href = file.url;
}
};
};
</script>
```
@/api/base.js 接口
~~~js
```
```
import { axios } from "@/http/axios";
const env = import.meta.env;
```
// 上传文件
// 定义上传文件的配置对象 uploadFile
export const uploadFile = {
// 上传文件的接口 URL,使用环境变量 VITE_BASE_API_URL 拼接
url: env.VITE_BASE_API_URL + "/admin-api/infra/file/upload",
// 请求头部信息,包括租户 ID 和授权 Token
headers: {
// 从本地存储获取租户 ID
"tenant-id": window.localStorage.getItem("tenantId"),
// 拼接授权 Token,并添加到 Authorization 头部
Authorization: `Bearer ${window.localStorage.getItem("qyy_token")}`,
},
};
```