北京網(wǎng)站備案號(hào)qq空間刷贊網(wǎng)站推廣
目錄
一、需求背景
二、落地實(shí)現(xiàn)?
1.文件上傳
圖片示例?
HTML代碼?
業(yè)務(wù)代碼
2.文件下載
圖片示例
方式一:代碼
方式二:代碼
3.文件預(yù)覽
圖片示例
方式一:代碼
方式二:代碼
一、需求背景
在一個(gè)愉快的年后,需求經(jīng)理提出需要完成對(duì)單個(gè)Excel文件的上傳、下載、預(yù)覽的功能,對(duì)于一個(gè)沒(méi)寫(xiě)過(guò)下載和預(yù)覽的后端來(lái)說(shuō),真的十分痛苦,經(jīng)過(guò)不斷百度+努力看別人的博客,最終實(shí)現(xiàn)如下圖所示
二、落地實(shí)現(xiàn)?
1.文件上傳
圖片示例?
HTML代碼?
<template><el-upload v-model="form.upload" ref="upload" name="file" action="" drag :on-remove="handleRemove" :on-success="handleSuccess" multiple :limit="1" accept=".xls,.xlsx" :before-upload="beforeUpload" :http-request="handleRequest" :on-exceed="handleExceed"><i class="el-icon-upload" style="color: #409eff"></i><div class="el-upload__tip"><span style="color: #333333;font-size: 13px">點(diǎn)擊或?qū)⑽募献У竭@里上傳</span></div><div class="el-upload__tip"><span style="color: #999999;font-size: 13px">僅支持單文件上傳,文件上傳行數(shù)最多1000,上傳格式支持:.xls .xlsx</span></div></el-upload>
<template>
?參數(shù)解釋
name="file":是傳到后端時(shí),它接收這個(gè)文件的參數(shù)名叫file,本人沒(méi)有仔細(xì)研究,因?yàn)樵谡{(diào)接口時(shí),可個(gè)性化定制參數(shù)名,后續(xù)貼的代碼會(huì)提到。
action="":這個(gè)Element官方文檔寫(xiě)的是一個(gè)上傳的固定鏈接,假的,用不了。通常在開(kāi)發(fā)中,也是自定義上傳邏輯,所以這里置空。
drag:啟用拖拽上傳,Element默認(rèn)是false,直接寫(xiě)drag,不寫(xiě):drag="true"就是true了。
show-file-list:顯示已上傳文件列表,就是上傳框下面的那行文件名,Element默認(rèn)是false
multiple:支持多選文件,通常與limit搭配使用。
:limit="1":多選文件數(shù)量,如只需要單個(gè)文件就設(shè)置1。
accept=".xls,.xlsx":接受上傳的文件類型,我的需求是只要Excel的。
:on-remove="handleRemove":文件列表移除文件時(shí)的方法,就是文件列表右邊那個(gè)小X觸發(fā)時(shí)調(diào)用的。
:on-success="handleSuccess":文件上傳成功時(shí)的方法,比如彈出一個(gè)上傳成功提示。
:before-upload="beforeUpload":上傳文件之前的方法,通常用于上傳文件前對(duì)文件的校驗(yàn)。
:http-request="handleRequest":自定義上傳方式的方法,比如遠(yuǎn)程調(diào)用。
:on-exceed="handleExceed":文件超出個(gè)數(shù)限制時(shí)的方法,比如彈出一個(gè)僅支持單個(gè)文件的提示。
class="el-upload__tip":這個(gè)是Element封裝好的樣式,我的需求是需要文字在上傳框里顯示,所以都用el-upload__tip,官方文檔還有個(gè)框外的用el-upload__text。
業(yè)務(wù)代碼
export default {name: "upload-dialog",data() {return {};},methods: {handleSuccess(response, file, fileList) {// 文件上傳成功的回調(diào)this.$message.success("上傳成功");},handleRemove(file, fileList) {console.log("刪除", file, fileList);// 看需要是否調(diào)用刪除接口},beforeUpload(file) {// 在這里進(jìn)行個(gè)性化校驗(yàn)const maxSize = 100 * 1024 * 1024; // 100MB(以字節(jié)為單位)if (file.size > maxSize) {// 這里可以添加你的提示邏輯(比如 Element UI 的 Message 警告)this.$message.warning("文件大小不能超過(guò) 100 MB");return false; // 阻止上傳}return true;},handleRequest(option) {// 自定義上傳函數(shù),用于并發(fā)上傳const formData = new FormData();// 這個(gè)file就是后端的接收這個(gè)文件的參數(shù)名,如果為其他,則設(shè)成其他formData.append("file", option.file);// 如果還需要其他參數(shù)比如id,name,就在這里繼續(xù)加// formData.append("id", xxx);// 發(fā)送請(qǐng)求,這個(gè)uploadApi是import進(jìn)來(lái)的,自己寫(xiě)uploadApi(formData).then(res => {// 自定義上傳方法的話,需要手動(dòng)觸發(fā)文件上傳成功的鉤子,不然文件狀態(tài)會(huì)一直處于readyoption.onSuccess(null, option.file);}).catch(error => {// 自定義上傳方法的話,需要手動(dòng)觸發(fā)文件上傳失敗的鉤子,不然文件狀態(tài)會(huì)一直處于readyoption.onError(error, option.file, null);});},// 文件超出個(gè)數(shù)限制時(shí)的鉤子handleExceed(files, fileList) {this.$message.warning("僅支持單個(gè)文件上傳");},},
};
2.文件下載
圖片示例
我是通過(guò)<a></a>標(biāo)簽去實(shí)現(xiàn)文件下載的,如果想通過(guò)點(diǎn)擊按鈕實(shí)現(xiàn),那么,在按鈕里面套塞<a></a>即可
方式一:代碼
<template><a :href="fileUrl" download>>文件</a>
</template>
export default {data() {return {fileUlr: 'www.aaa.com/test.txt'};},
}
這個(gè)href放是一個(gè)像www.aaa.com/test.txt這樣的cdn文件地址,點(diǎn)擊就可以直接下載到本地。
如果需要通過(guò)二進(jìn)制流、Blob對(duì)象實(shí)現(xiàn)的話,則自定義按鈕,觸發(fā)方法去調(diào)用。(詳情請(qǐng)看方式二)
方式二:代碼
<template><el-button type="text" @click="downloadFile(fileName)"><span style="color: #0000FF">文件名</span></el-button>
</template>
export default {data() {return {};},methods: {downloadFile(fileName) {// 生成隨機(jī)數(shù)據(jù)(示例:5行3列)const data = [["Name", "Age", "Join Date"], // 表頭...Array.from({length: 5}, (_, i) => [`User ${i + 1}`, // 姓名Math.floor(Math.random() * 30 + 20), // 隨機(jī)年齡 (20-50)new Date().toISOString().split("T")[0], // 當(dāng)前日期]),];// 創(chuàng)建工作表const worksheet = XLSX.utils.aoa_to_sheet(data);// 創(chuàng)建工作簿const workbook = XLSX.utils.book_new();XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");// 生成 Excel 文件const excelBuffer = XLSX.write(workbook, {bookType: "xlsx",type: "array",});const blob = new Blob([excelBuffer], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",});// 創(chuàng)建一個(gè)鏈接元素const link = document.createElement('a');link.href = URL.createObjectURL(blob);link.download = fileName; // 設(shè)置下載的文件名// 觸發(fā)下載link.click();// 釋放 URL 對(duì)象URL.revokeObjectURL(link.href);this.$message.success("文件下載成功");},}
}
3.文件預(yù)覽
圖片示例
我的需求是:點(diǎn)擊文件名,瀏覽器新打開(kāi)一個(gè)標(biāo)簽頁(yè),展示文件內(nèi)容。
這個(gè)需要在route中額外添加一個(gè)路由映射
{path: '/preview',name: 'preview',meta: { title: '文件預(yù)覽', requiresAuth: false },component: () => import('@/views/preview.vue')
},
還需要額外結(jié)合@vue-office/excel寫(xiě)頁(yè)面?
npm install @vue-office/excel vue-demi
方式一:代碼
入口代碼
<template><el-button type="text"><a :href="'#/preview?fileUrl='+fileUrl" target="_blank">詳情</a></el-button>
</template>
export default {data() {return {fileUlr: 'www.aaa.com/test.txt'};},
}
?頁(yè)面代碼
<template><vue-office-excel :src="excel" @rendered="rendered" @error="errorHandler"/>
</template>
<script>
//引入VueOfficeExcel組件
import VueOfficeExcel from "@vue-office/excel";
//引入相關(guān)樣式
import "@vue-office/excel/lib/index.css";
//引入解析Excel文件組件
import XLSX from "xlsx";export default {components: {VueOfficeExcel,},data() {return {// 設(shè)置文檔地址,支持三種格式// string: Excel文件的網(wǎng)絡(luò)地址,如cdn地址// ArrayBuffer:以ArrayBuffer格式讀取Excel文件的內(nèi)容// Blob:以Blob格式讀取Excel文件的內(nèi)容excel: "",};},mounted() {this.getExcel();},methods: {rendered() {console.log("渲染完成");},errorHandler() {console.log("渲染失敗");},getExcel() {this.excel = this.$route.query.fileUrl;}},
};
</script>
這樣直接就是瀏覽器新打開(kāi)一個(gè)標(biāo)簽頁(yè)展示文件內(nèi)容。與文件下載十分相似。
如果需要使用二進(jìn)制流、Blob對(duì)象打開(kāi)的話。(詳情請(qǐng)看方式二)
方式二:代碼
入口代碼
<template><el-button type="text"><a :href="'#/preview'" target="_blank">詳情</a></el-button>
</template>
頁(yè)面代碼
<template><vue-office-excel :src="excel" @rendered="rendered" @error="errorHandler"/>
</template>
<script>
//引入VueOfficeExcel組件
import VueOfficeExcel from "@vue-office/excel";
//引入相關(guān)樣式
import "@vue-office/excel/lib/index.css";
//引入解析Excel文件組件
import XLSX from "xlsx";export default {components: {VueOfficeExcel,},data() {return {// 設(shè)置文檔地址,支持三種格式// string: Excel文件的網(wǎng)絡(luò)地址,如cdn地址// ArrayBuffer:以ArrayBuffer格式讀取Excel文件的內(nèi)容// Blob:以Blob格式讀取Excel文件的內(nèi)容excel: "",};},mounted() {this.createRandomExcel();},methods: {rendered() {console.log("渲染完成");},errorHandler() {console.log("渲染失敗");},// 創(chuàng)建隨機(jī) Excel 文件createRandomExcel() {// 生成隨機(jī)數(shù)據(jù)(示例:5行3列)const data = [["Name", "Age", "Join Date"], // 表頭...Array.from({length: 5}, (_, i) => [`User ${i + 1}`, // 姓名Math.floor(Math.random() * 30 + 20), // 隨機(jī)年齡 (20-50)new Date().toISOString().split("T")[0], // 當(dāng)前日期]),];// 創(chuàng)建工作表const worksheet = XLSX.utils.aoa_to_sheet(data);// 創(chuàng)建工作簿const workbook = XLSX.utils.book_new();XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");// 生成 Excel 文件const excelBuffer = XLSX.write(workbook, {bookType: "xlsx",type: "array",});const blob = new Blob([excelBuffer], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",});this.excel = blob;},},
};
</script>
上述代碼,也適用于展示W(wǎng)ord和PPT文件,修改對(duì)應(yīng)的格式即可。?