vue3+ts+element-plus上传文件,预览文件
场景:使用element-plus的el-upload标签,手动上传文件,可预览docx,xlsx,pdf,jpg,jpeg,png(本地资源以及网络资源)。
1、使用el-upload标签
检查上传文件的文件格式与大小
上传的附件信息在fileList中,组装接口所需数据进行上传
使用docx-preview插件预览docx类型的文件
使用xlsx插件预览xlsx文件
这里遇到了问题,引入xlsx插件的时候出现"export ‘default’ (imported as ‘XLSX’) was not found in 'xlsx’报错
解决:
直接将import XLSX from 'xlsx’改为import * as XLSX from 'xlsx/xlsx.mjs’即可
图片预览
pdf预览
完整代码
<template><el-dialog
v-model="uploadDialogVisible"
title="上传"
width="800px"
label-width="100px"@close="uploadDialogVisible = false"><el-upload
ref="uploadRef"
v-model:file-list="fileList"class="upload-demo"
drag
:multiple="true":auto-upload="false":accept="props.allowType":limit="props.limit":before-upload="beforeAvatarUpload":on-preview="previewFun"><el-icon class="el-icon--upload"><upload-filled /></el-icon><div class="el-upload__text"><em>选择文件</em></div><template #tip><div class="el-upload__tip">
支持格式:{{ props.allowType }};限制大小{{ props.size }}M</div></template></el-upload><template #footer><span class="dialog-footer"><el-button round @click="cancelFun">取消</el-button><el-button round type="primary"@click="submitFun">确定</el-button><el-button round type="primary"@click="getFileList">获取文件</el-button
></span></template></el-dialog><!-- 查看 --><viewer ref="fileViewerRef":dialog-doc="dialogDoc"/></template><script setup lang="ts">/* eslint-disable */import{ defineProps, defineEmits, ref, reactive, computed }from"vue";importtype{
FormInstance,
UploadProps,
UploadUserFile,
UploadRawFile
}from"element-plus";import{ ElMessage }from"element-plus";import{ UploadFilled }from"@element-plus/icons-vue";import{ api }from"@/api";import SparkMD5 from"spark-md5";import Viewer from"./viewer.vue";interfaceProps{
uploadDialogVisible?:boolean;
allowType?:string;
limit?:number;
fileList?:any;
size?:number;
fileExtendId?:string;
fileCategory?:number;
folderName?:string;
systemSource?:string;
uploadUrl?:string;}//propsconst props:any=withDefaults(defineProps<Props>(),{
uploadDialogVisible:false,
allowType:"doc,docx,jpg,jpeg,png,xlsx,pdf",
limit:5,
size:5,
fileExtendId:"",
fileCategory:2,
folderName:"ceshi",
systemSource:"ceshi",
uploadUrl:"http://192.168.188.3:7001"});const uploadDialogVisible =computed(()=>{return props.uploadDialogVisible;});const uploadRef =ref<FormInstance>();const fileList =ref(([]asany));const fileExtendId =ref("682D0E35121A4D4E831714CDACD5A18E");constbeforeAvatarUpload=()=>{const flag =ref(true);
fileList.value.forEach((item:any)=>{console.log(item);const type = item.name.split(".")[1];if(props.allowType.indexOf(type)==-1){ElMessage({
type:"error",
message:`格式错误,支持格式:${props.allowType}!`});
flag.value =false;return;}elseif(item.size /1024/1024> props.size){
ElMessage.error(`文件最大${props.size}MB!`);
flag.value =false;return;}});return flag.value;};//取消constcancelFun=()=>{emit("cancel",false);};constsubmitFun=(formEl: FormInstance |undefined)=>{// 判断是否有文件需要上传if(fileList.value.length){const flag =beforeAvatarUpload();if(!flag){return;}// 组合数据const params =newFormData();const fileConfigs:any=[];if(fileList.value.length){
fileList.value.forEach((item:any, index:number)=>{// 判断一下是不是新上传的if(item.id){
fileConfigs.push({
fileId: item.id,
fileName: item.name,
sort:++index,// 必须从1开始,依次12345往下
md5:""});}else{
params.append("file", item.raw);const spark =newSparkMD5.ArrayBuffer();
spark.append(item.raw);const md5 = spark.end();
fileConfigs.push({
fileId:"",
fileName: item.name,
sort:++index,// 必须从1开始,依次12345往下
md5: md5
});};});}
params.append("fileExtendId", fileExtendId.value);
params.append("fileCategory", props.fileCategory);
params.append("folderName", props.folderName);
params.append("systemSource", props.systemSource);
params.append("FileConfigs",JSON.stringify(fileConfigs));console.log(params);
api.adminCenter.UploadFiles(params).then((res:any)=>{if(res.status.code ==200){
fileExtendId.value = res.result.fileExtendId;// 拿到了组合id,继续做业务}});}else{console.log("直接做业务");}};// 获取附件constgetFileList=()=>{
api.adminCenter
.GetFileList({
fileExtendIds: fileExtendId.value
}).then((res:any)=>{if(res.status.code ==200){
res.result.forEach((ele:any)=>{
ele.name = ele.fileOldName;
fileList.value.push(ele);});}else{}});};let dialogDoc:any=ref(false);const fileViewerRef =ref<any>(null);constpreviewFun=(file:any)=>{console.log(file.halfPath);
dialogDoc.value =true;let data = file;// 上传过的文件组成完成的网络路径if(file.halfPath){
data.src =`${props.uploadUrl}${file.halfPath}`;}const suffix = data.name.split(".")[1];if(suffix =="docx"){
fileViewerRef.value?.viewDocx(data);}elseif(suffix =="xlsx"){
fileViewerRef.value?.viewXlsx(data);}elseif(suffix =="jpg"|| suffix =="jpeg"|| suffix =="png"){
fileViewerRef.value?.viewImg(data);}elseif(suffix =="pdf"){
fileViewerRef.value?.viewPdf(data);}};// 声明emitconst emit =defineEmits(["cancel"]);</script>
<template><!-- doc --><el-dialog
v-model="dialogDocxValue":title="dialogTitle"
width="80%"@close="dialogDocxClose"><div ref="docxRef"class="word-div"></div></el-dialog><!-- xlsx --><el-dialog
v-model="dialogXlsxValue":title="dialogTitle"
width="80%"@close="dialogXlsxClose"><div ref="xlsxRef"class="xlsx-div"><el-tabs v-model="activeName" type="border-card"><el-tab-pane
v-for="(item, index) in excelSheet":key="index":label="item.name":name="item.name"><div class="table" v-html="item.html"></div></el-tab-pane></el-tabs></div></el-dialog><!-- 图片 --><el-dialog
v-model="dialogImgValue":title="dialogTitle"
width="80%"@close="dialogImgClose"><div class="img-div"><el-image :src="fileData.src":alt="fileData.fileOldName"/></div></el-dialog><!-- pdf --><el-dialog
v-model="dialogPdfValue":title="dialogTitle"
width="80%"@close="dialogPdfClose"><div class="pdf-div"><iframe
id="pdfRef":src="iframeUrl"
frameborder="0"
style="width: 100%; height: 99%"></iframe></div></el-dialog></template><script setup lang="ts">import axios from"axios";import{ defineProps, ref, reactive, computed, nextTick }from"vue";import{ renderAsync }from"docx-preview";import*asXLSXfrom"xlsx";interfaceProps{
dialogDocx?:boolean;
dialogXlsx?:boolean;
dialogTitle?:string;}const props:any=withDefaults(defineProps<Props>(),{
dialogDocx:false,
dialogTitle:"",
dialogXlsx:false});const dialogDocxValue:any=ref(false);let dialogTitle =computed(()=>{return props.dialogTitle;});const fileHtml =ref("");const docxRef =ref<any>();// doc 文档预览constviewDocx=(data:any)=>{
docxRef.value ="";
dialogDocxValue.value =true;console.log(data);if(data.src){// 已上传的文件axios({
url: data.src,
method:"get",
responseType:"blob"}).then((res)=>{console.log(res);if(res.status ==200){const content = res.data;const blob =newBlob([content]);nextTick(()=>{
dialogDocxValue.value =true;renderAsync(blob, docxRef.value);
dialogTitle = data.fileOldName || data.name;});}});}else{// 本地文件const blob =newBlob([data.raw]);nextTick(()=>{
dialogDocxValue.value =true;renderAsync(blob, docxRef.value);
dialogTitle = data.fileOldName || data.name;});}};const dialogXlsxValue:any=ref(false);const excelSheet:any=ref([]);const activeName =ref("");constdialogDocxClose=()=>{
dialogDocxValue.value =false;
docxRef.value ="";};// xlsx 预览constviewXlsx=(data:any)=>{
dialogXlsxValue.value =true;console.log(data);if(data.src){axios({
url: data.src,
method:"get",
responseType:"blob"}).then((res)=>{console.log(res);if(res.status ==200){const content = res.data;// const blob = new Blob(content);const reader =newFileReader();
reader.readAsArrayBuffer(content);
reader.onload=function(loadEvent:any){const arrayBuffer = loadEvent.target["result"];const workbook =XLSX.read(newUint8Array(arrayBuffer),{
type:"array"});const list =[];const sheetNames = workbook.SheetNames;
activeName.value = sheetNames[0];for(const p of sheetNames){let html ="";try{
html =XLSX.utils.sheet_to_html(workbook.Sheets[p]);}catch(e){
html ="";}const map ={
name: p,
html: html
};
list.push(map);}
excelSheet.value = list;
dialogTitle = data.fileName || data.name;};}});}else{const blob =newBlob([data.raw]);const reader =newFileReader();
reader.readAsArrayBuffer(blob);
reader.onload=function(loadEvent:any){const arrayBuffer = loadEvent.target["result"];const workbook =XLSX.read(newUint8Array(arrayBuffer),{
type:"array"});const list =[];const sheetNames = workbook.SheetNames;
activeName.value = sheetNames[0];for(const p of sheetNames){let html ="";try{
html =XLSX.utils.sheet_to_html(workbook.Sheets[p]);}catch(e){
html ="";}const map ={
name: p,
html: html
};
list.push(map);}
excelSheet.value = list;
dialogTitle = data.fileName || data.name;};}};constdialogXlsxClose=()=>{
dialogXlsxValue.value =false;
excelSheet.value ="";
activeName.value ="";};const fileData:any=ref({});const dialogImgValue:any=ref(false);// 图片预览constviewImg=(data:any)=>{if(data.src){// 已上传的图片
fileData.value = data;}else{// 本地图片const freader =newFileReader();
freader.readAsDataURL(data.raw);
freader.onload=(e:any)=>{
fileData.value ={
src: e.target.result,
id:newDate(),
fileName: data.fileOldName || data.name
};};}
dialogTitle = data.fileOldName || data.name;
dialogImgValue.value =true;};constdialogImgClose=()=>{
dialogImgValue.value =false;};const dialogPdfValue:any=ref(false);const iframeUrl:any=ref("");const pdfRef =ref<any>();constviewPdf=(data:any)=>{if(data.src){axios({
url: data.src,
method:"get",
responseType:"blob"}).then((res)=>{if(res.status ==200){// 把文件流转化为url
iframeUrl.value =URL.createObjectURL(res.data);
dialogPdfValue.value =true;}});}else{
iframeUrl.value =URL.createObjectURL(data.raw);
dialogPdfValue.value =true;}};constdialogPdfClose=()=>{
dialogPdfValue.value =false;};defineExpose({
viewDocx,
viewXlsx,
viewImg,
viewPdf
});</script><style scoped lang="scss">.word-div {
height:calc(70vh);
overflow: auto;}.xlsx-div {
height:calc(70vh);
overflow: auto;}.img-div {
height:calc(70vh);
overflow: auto;
img {
width:100%;
height:100%;}}.pdf-div {
height:calc(70vh);
overflow: auto;}</style><style lang="scss">.xlsx-div {.table-html-wrap table {
border-right: 1px solid #fff;
border-bottom: 1px solid #e8eaec;
border-collapse: collapse;// margin: auto;}.table-html-wrap table td {
border-left: 1px solid #e8eaec;
border-top: 1px solid #e8eaec;
white-space: wrap;
text-align: left;
min-width: 100px;
padding: 4px;}
table {
border-top: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
width:100%;// overflow: auto;
tr {
height: 44px;}
td {
min-width: 200px;
max-width: 400px;
padding: 4px 8px;
border-right: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;}}.el-tabs--border-card >.el-tabs__content {
overflow-x: auto;}}</style>
本文转载自: https://blog.csdn.net/weixin_42255789/article/details/128716185
版权归原作者 人鱼小姐ww 所有, 如有侵权,请联系我们删除。
版权归原作者 人鱼小姐ww 所有, 如有侵权,请联系我们删除。