vue上傳各種文件,并預覽組件,(預覽,下載),下載resources目錄下文件

前端組件vue

最終效果
在這里插入圖片描述

<template><div ><div class="file-list" v-if="existingFiles.length > 0"><div class="file-card" v-for="(file, index) in existingFiles" :key="file.id"><div class="file-preview"><i v-if="file.type === 'pdf'" class="el-icon-document pdf-preview"></i><i v-else-if="file.type === 'doc' || file.type === 'docx'" class="el-icon-document doc-preview"></i><i v-else-if="file.type === 'image'" class="el-icon-picture-outline"></i><i v-else class="el-icon-document other-preview"></i></div><div class="file-name">{{ file.originalFileName }}</div><div class="file-actions"><el-button type="primary" icon="el-icon-view" size="mini" circle @click="handlePreview(file)"></el-button><el-button type="success" icon="el-icon-download" size="mini" v-if="showDownLoadBut" circle @click="downloadFile(file)"></el-button><el-button type="danger" icon="el-icon-delete" size="mini" v-if="showDeleteBut" circle @click="handleDelete(file, index)"></el-button></div></div></div><el-alertv-elsetitle="當前尚未上傳任何合同"type="warning"show-iconstyle="margin: 20px 0;"></el-alert><div class="upload-demo" v-if="existsUploadBut"><el-uploadref="upload":action="uploadUrl":headers="headers"multiple:on-success="handleUploadSuccess":show-file-list="false"accept=".pdf,.doc,.docx,.jpg,.jpeg,.png"><el-button size="medium" type="primary" icon="el-icon-plus">添加合同文件</el-button><div slot="tip" class="el-upload__tip" style="margin-top: 10px;">支持上傳PDF、Word文檔和圖片文件,單個文件不超過10MB</div></el-upload></div><!-- 文件預覽彈窗 --><el-dialog:title="previewTitle":visible.sync="previewVisible"width="80%"top="5vh"><div class="preview-container"><img v-if="previewType === 'image'" :src="previewUrl"><iframev-else-if="previewType === 'pdf'":src="previewUrl"class="preview-iframe"></iframe><div v-else><p>不支持在線預覽,請下載后查看</p><el-button type="primary" icon="el-icon-download" @click="downloadFile(previewFile)">下載文件</el-button></div></div></el-dialog></div>
</template>
<script>export default {name: "FileUploadPreview",props:{// 上傳文件目錄fileDirectory: {type: String,require: true,default: ''},// 文件列表fileList:{type:Array,default:()=>[]},// 上傳按鈕existsUploadBut:{type: Boolean,default: false},// 下載按鈕是否顯示showDownLoadBut:{type: Boolean,default: false},// 刪除按鈕showDeleteBut:{type: Boolean,default: false}},data() {return {previewVisible: false,existingFiles: this.fileList,previewUrl: '',previewType: '',previewTitle: '查看附件',previewFile: null,// 請求頭 - 包含認證Tokenheaders: {Authorization: 'Bearer ' + this.$store.getters.token},uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload?fileDirectory="+this.fileDirectory,imageDialogVisible: false, // 圖片彈窗可見性previewVisible: false, // 預覽彈窗可見性previewImageUrl: '', // 預覽圖片URLtempImageList: [], // 臨時圖片列表};},created() {},methods: {// 移除待上傳文件removeNewFile(index) {this.existingFiles.splice(index, 1);},// 預覽文件handlePreview(file) {this.previewFile = file;this.previewTitle = `預覽文件 - ${file.originalFileName}`;this.previewUrl = file.url==null?file.filePath:"";this.previewType = this.getFileType(file.originalFileName);this.previewVisible = true;},// 刪除文件handleDelete(file, index) {this.$confirm(`確定要刪除合同 "${file.originalFileName}"?`, '提示', {confirmButtonText: '確定',cancelButtonText: '取消',type: 'warning'}).then(() => {// 模擬API刪除請求setTimeout(() => {this.existingFiles.splice(index, 1);this.$message.success(`合同 "${file.originalFileName}" 已刪除`);}, 500);}).catch(() => {});},// 獲取文件類型getFileType(filename) {const ext = filename.split('.').pop().toLowerCase();if (['jpg','jpeg','png','gif'].includes(ext)) return 'image';if (ext === 'pdf') return 'pdf';if (['doc','docx'].includes(ext)) return 'doc';return 'other';},// 格式化文件大小formatFileSize(bytes) {if (bytes === 0) return '0 Bytes';const k = 1024;const sizes = ['Bytes', 'KB', 'MB', 'GB'];const i = Math.floor(Math.log(bytes) / Math.log(k));return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];},// 下載文件downloadFile(file) {this.$message.info(`開始下載: ${file.originalFileName}`);// 實際項目中這里應該是文件下載邏輯this.$download.systemDownLoadFile(file.filePath,file.originalFileName);},// 打開圖片彈窗openImageDialog(row) {this.imageDialogVisible = true;// 加載已有圖片 (實際項目中從后端獲取)getWarehouseFiles(row.uuid).then(resp=>{this.tempImageList = resp.data;});},// 圖片上傳前校驗beforeImageUpload(file) {const isImage = file.type.startsWith('image/');const isPdf = file.type === 'application/pdf';const isLt10M = file.size / 1024 / 1024 < 10;if (!(isImage || isPdf)) {this.$message.error('只能上傳圖片或PDF文件!');return false;}if (!isLt10M) {this.$message.error('文件大小不能超過10MB!');return false;}return true;},// 圖片上傳成功處理handleUploadSuccess(response, file, fileList) {// 實際項目中根據接口返回調整//   this.newFiles = fileList.map(f => ({//     originalFileName: f.response?.originalFilename || f.originalFileName,//     newFileName: f.response?.newFileName || f.newFileName,//     filePath: f.response?.filePath || f.filePath,//     fileSize: f.response?.size || f.fileSize,//     fileShowSize: f.response?.showSize || f.fileShowSize,//     fileType: f.response?.fileType || f.fileType,//     warehouseManagerUuid: f.response?.warehouseManagerUuid || f.warehouseManagerUuid,//     url: f.response?.url || f.url,//   }));debuggerif(response.code==200){var tempData={originalFileName: response.originalFilename,newFileName:response.newFileName,filePath:response.filePath,fileSize:response.size,fileShowSize: response.showSize,fileType:response.fileType,name:response.originalFilename,url:response.url}this.existingFiles.push(tempData);}},// 預覽圖片handlePictureCardPreview(file) {this.previewImageUrl = file.url;this.previewVisible = true;},// 移除圖片handleRemove(file, fileList) {this.tempImageList = fileList;},}
};
</script>
<style scoped>body {font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;background-color: #f5f7fa;color: #333;padding: 20px;}.container {max-width: 1200px;margin: 0 auto;background: white;border-radius: 8px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);padding: 20px;}.header {display: flex;justify-content: space-between;align-items: center;padding: 15px 0;border-bottom: 1px solid #ebeef5;margin-bottom: 20px;}.header h1 {color: #409EFF;font-size: 24px;}.sub-title {color: #909399;margin: 10px 0 20px;}.contract-actions {display: flex;gap: 10px;margin-bottom: 20px;}.file-card {position: relative;border-radius: 6px;overflow: hidden;transition: all 0.3s;border: 1px solid #ebeef5;}.file-card:hover {box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);}.file-name {padding: 8px;font-size: 12px;text-align: center;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;background: #f8f8f8;}.file-actions {position: absolute;top: 5px;right: 5px;display: flex;gap: 5px;opacity: 0;transition: opacity 0.3s;}.file-card:hover .file-actions {opacity: 1;}.file-preview {display: flex;align-items: center;justify-content: center;height: 100px;background: #f5f7fa;}.file-preview i {font-size: 40px;color: #409EFF;}.pdf-preview {color: #F56C6C;}.doc-preview {color: #409EFF;}.other-preview {color: #909399;}.file-list {display: grid;grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));gap: 15px;margin-top: 20px;}.preview-container {width: 100%;height: 70vh;}.preview-container img {max-width: 100%;max-height: 100%;display: block;margin: 0 auto;}.preview-iframe {width: 100%;height: 100%;border: none;}.footer {margin-top: 20px;text-align: center;color: #909399;font-size: 14px;padding: 10px;border-top: 1px solid #ebeef5;}.upload-demo {margin-top: 20px;}.demo-table {margin-top: 20px;}.status-badge {display: inline-block;padding: 2px 8px;border-radius: 4px;font-size: 12px;}.status-success {background: #f0f9eb;color: #67c23a;}.status-warning {background: #fdf6ec;color: #e6a23c;}
</style>

使用瀏覽器確認保存路徑

在這里插入圖片描述在這里插入圖片描述

systemDownLoadFile(filePath,fileName) {var url = baseURL + "/common/systemDownLoadFile?filePath=" + encodeURIComponent(filePath)+"&fileName="+encodeURIComponent(fileName);axios({method: 'get',url: url,responseType: 'blob',headers: { 'Authorization': 'Bearer ' + getToken() }}).then((res) => {const isBlob = blobValidate(res.data);if (isBlob) {const blob = new Blob([res.data])this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))} else {this.printErrMsg(res.data);}})},

后端代碼

 /*** 下載文件** @param filePath 文件路徑* @param fileName 文件原始名* @param response* @param request*/@GetMapping("/systemDownLoadFile")public void systemDownLoadFile(@RequestParam("filePath") String filePath, @RequestParam("fileName") String fileName, HttpServletResponse response,HttpServletRequest request) {try {if (!FileUtils.checkAllowDownload(fileName)) {throw new Exception(StringUtils.format("文件名稱({})非法,不允許下載。 ", fileName));}String configByKey = iSysConfigService.selectConfigByKey(SysConfigConstants.UPLOAD_ROOT);
//            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);String fileAllPath = configByKey + filePath;// 上傳文件路徑if (StringUtils.isEmpty(configByKey)) {log.info("服務器文件上傳地址不能為空,請檢查參數設置的  {} 是否配置值", SysConfigConstants.UPLOAD_ROOT);return;}response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);FileUtils.setAttachmentResponseHeader(response, fileName);FileUtils.writeBytes(fileAllPath, response.getOutputStream());} catch (Exception e) {log.error("下載文件失敗", e);}}

下載resources目錄下的文件

在這里插入圖片描述

@GetMapping("/downloadTemplates")ResponseEntity<Resource> downloadFile(@RequestParam("fileName") String fileName) {// 驗證文件名安全(防止路徑遍歷攻擊)if (!isValidFileName(fileName)) {throw new FileDownloadException("文件名不合法", HttpStatus.BAD_REQUEST);}// 從resources目錄加載文件Resource resource = new ClassPathResource("templates/" + fileName);// 檢查文件是否存在if (!resource.exists()) {throw new FileDownloadException("文件不存在", HttpStatus.NOT_FOUND);}try {// 設置響應頭HttpHeaders headers = new HttpHeaders();headers.add(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=\"" + encodeFilename(fileName) + "\"");return ResponseEntity.ok().headers(headers).contentLength(resource.contentLength()).contentType(MediaType.APPLICATION_OCTET_STREAM).body(resource);} catch (IOException e) {return ResponseEntity.internalServerError().build();}}/*** 安全驗證文件名(防止路徑遍歷攻擊)** @param fileName* @return*/private boolean isValidFileName(String fileName) {return fileName != null &&!fileName.contains("..") &&!fileName.contains("/") &&!fileName.contains("\\");}/*** 處理中文文件名亂碼問題** @param fileName* @return*/private String encodeFilename(String fileName) {return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86858.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86858.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86858.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【CS創世SD NAND征文】SD NAND賦能新一代兒童智能玩具

基于全志F1C100S的高可靠存儲方案 文章目錄 基于全志F1C100S的高可靠存儲方案[toc]前言 一、應用產品介紹&#xff1a;兒童智能玩具的需求演變二、技術方案介紹&#xff1a;構建智能玩具的"大腦"與"記憶庫"三、核心技術模塊分析3.1 主控芯片&#xff1a;全…

mac觸摸板設置右鍵

在 Mac 筆記本上&#xff0c;觸摸板默認沒有物理左右鍵分區&#xff0c;但可以通過以下方式實現“右鍵”功能&#xff08;稱為 輔助點按&#xff09;&#xff1a; 一、啟用與使用右鍵&#xff08;輔助點按&#xff09; 步驟1&#xff1a;檢查系統設置 點擊屏幕左上角 &#x…

穩定幣發行量創紀錄地超過 Visa 交易量

穩定幣發行量創紀錄地超過 Visa 交易量 穩定幣的崛起正在重塑全球金融格局&#xff0c;華夏基金首席執行官甘天&#xff08;Gan Tian&#xff09;強調了穩定幣的快速增長&#xff0c;并指出穩定幣的交易量在短短五年內就超過了Visa 40年的交易量。這凸顯了貨幣使用的轉變。 穩…

編程 IDE 混戰簡史:從 Copilot 到 Claude Code,一場重塑開發方式的戰爭

unsetunset引言&#xff1a;開發新紀元的序幕unsetunset 編程世界&#xff0c;從最初依賴打孔卡和簡陋的命令行工具&#xff0c;到如今功能琳瑯滿目的集成開發環境&#xff08;IDE&#xff09;&#xff0c;每一步都見證了效率與智能的飛躍。IDE作為開發者與代碼交互的核心界面&…

軟測八股--計算機網絡

計算機網絡基礎 局域網廣域網 局域網&#xff1a;一個區域內由多臺計算機互聯成的計算機組&#xff08;學校&#xff0c;辦公室&#xff0c;公司/學校等&#xff09;。可以實現文件管理&#xff0c;應用軟件管理&#xff0c;答應及管理&#xff0c;掃描儀共享等。是封閉的&am…

某省職業院校技能大賽 高職組“信息安全管理與評估”賽項第二部分:應急響應

&#xff01;&#xff01;&#xff01;需要環境可私信博主&#xff01;&#xff01;&#xff01; &#xff01;&#xff01;&#xff01;若有錯誤歡迎指正&#xff01;:) 序號任務要求1提交攻擊者的兩個內網IP地址2提交網站管理員用戶的用戶名和密碼3提交黑客得到 mysql 服務的…

OkHttp 簡單配置

OkHttpClient 的簡單配置&#xff0c;包含重試&#xff0c;線程池 Configuration public class OkHttpConfig {Bean("deSourceOkHttp")public OkHttpClient okHttpClient() {return new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS).readTimeout(3…

群暉nas安裝moodle跳坑記錄

1&#xff0c;套件里面直接安裝 會安裝好幾個依賴&#xff0c;包括php apach &#xff0c;數據庫。這些安裝的時間就比較長。 安裝完成后自動安裝 Moodle。 過程也很長數據庫里面的表有接近500張。 2&#xff0c;安裝位置 順便提一下 nas程序的安裝位置 這兩個位置好像都不是…

鴻蒙HarmonyOS 5小游戲實踐:打磚塊游戲(附:源代碼)

打磚塊是一款經典的游戲&#xff0c;它簡單易懂卻又充滿挑戰性。本文將介紹如何使用ArkUI框架開發一個完整的打磚塊游戲&#xff0c;涵蓋游戲邏輯設計、UI實現和交互處理等核心內容。 游戲架構設計 我們的打磚塊游戲采用了組件化設計&#xff0c;主要分為兩個部分&#xff1a;…

Flutter MobX 響應式原理與實戰詳解

&#x1f4da; Flutter 狀態管理系列文章目錄 Flutter 狀態管理(setState、InheritedWidget、 Provider 、Riverpod、 BLoC / Cubit、 GetX 、MobX 、Redux) setState() 使用詳解&#xff1a;原理及注意事項 InheritedWidget 組件使用及原理 Flutter 中 Provider 的使用、注…

淺談國產數據庫多租戶方案:提升云計算與SaaS的資源管理效率

近年來&#xff0c;“數據庫多租戶”這一概念在技術圈內頻頻出現&#xff0c;成為云計算和SaaS&#xff08;軟件即服務&#xff09;架構中的重要組成部分。多租戶架構不僅為企業提供了高效的資源隔離與共享解決方案&#xff0c;還能大幅降低成本&#xff0c;提高系統的可擴展性…

Wpf的Binding

前言 wpf的Binding就像一個橋梁&#xff0c;它的作用就是連接邏輯層與界面層&#xff0c;既能夠把邏輯層的數據搬到界面層展示&#xff0c;又能將界面層的數據更改后傳遞到邏輯層&#xff0c;Binding的數據來源就是Binding的源&#xff0c;數據展示的地方就是Binding的目標。 …

嵌入式單片機中SPI串行外設接口控制與詳解

串行外設接口(Serial Peripheral Interface)的簡稱也叫做SPI,是一種高速的、全雙工同步通信的一種接口,串行外設接口一般是需要4根線來進行通信(NSS、MISO、MOSI、SCK),但是如果打算實現單向通信(最少3根線),就可以利用這種機制實現一對多或者一對一的通信。 第一:…

【世紀龍科技】新能源汽車動力電池總成裝調與檢修教學軟件

在新能源汽車產業“技術迭代快、安全要求高、實操風險大”的背景下&#xff0c;職業院校如何以“項目式教學改革”為突破口&#xff0c;破解傳統實訓“高成本、高風險、低效率”的困局&#xff1f;江蘇世紀龍科技以桌面VR沉浸式技術為支點&#xff0c;推出《新能源動力電池總成…

GO泛型編程面試題及參考答案

目錄 什么是 Go 中的泛型?Go 從哪個版本開始支持泛型? 在 Go 中如何定義一個帶類型參數的函數? 如何為結構體添加類型參數? 使用 any 關鍵字和自定義類型約束有什么區別? 泛型中~T 的語義及其實際應用是什么? 如何在函數中使用多個類型參數?舉例說明。 Go 泛型支…

ReactRouter-404路由配置以及兩種路由模式

404路由 場景&#xff1a;當瀏覽器輸入url的路徑在整個路由配置中都找不到對應的path&#xff0c;為了用戶體驗&#xff0c;可以使用404兜底組件進行渲染 實現步驟 準備一個404組件在路由表數組的末尾&#xff0c;以*號作為路由path配置路由 新建404組件 const NotFound (…

《Kubernetes》Service 詳解+Ingress

主要介紹kubernetes的流量負載組件&#xff1a;Service和Ingress。 1. Service 1.1 Service介紹 在kubernetes中&#xff0c;pod是應用程序的載體&#xff0c;我們可以通過pod的ip來訪問應用程序&#xff0c;但是pod的ip地址不是固定的&#xff0c;這也就意味著不方便直接采用…

常見網絡知識,寬帶、路由器

常見網絡知識&#xff0c;寬帶、路由器 1、關于光貓、橋接和路由接法 現在的光貓都帶有路由功能&#xff0c;即光貓、路由一體。不需要路由器也能讓設備連上&#xff0c;但是一般來說路由功能穿墻有限&#xff0c;放在弱電箱/多媒體箱里的光貓發射出來的wifi信號其實是很難在…

Android應用緩存清理利器:WorkManager深度實踐指南

本文將帶你全面掌握使用WorkManager實現緩存清理的技術方案&#xff0c;從基礎原理到性能優化&#xff0c;提供完整代碼實現和工程實踐指南 一、緩存清理的必要性與挑戰 在Android應用開發中&#xff0c;緩存管理是優化應用性能的關鍵環節。隨著應用使用時間增長&#xff0c;緩…

如何理解構件“可獨立部署”的特性

構件的“可獨立部署”特性是其區別于普通代碼模塊的核心特征之一&#xff0c;我們可以通過生活案例和技術原理解釋來理解這一特性&#xff1a; 一、生活類比&#xff1a;從“家電維修”看獨立部署 假設你家的空調壞了&#xff0c;維修時只需拆開空調外機更換壓縮機&#xff0…