当前位置: 首页 > news >正文

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.lryc.cn/news/578232.html

相关文章:

  • 云上攻防—Docker安全容器逃逸特权模式危险挂载
  • 计算机网络(一)层
  • 3.前端和后端参数不一致,后端接不到数据的解决方案
  • 基于C#的OPCServer应用开发,引用WtOPCSvr.dll
  • 中钧科技亮相2025 亚欧商品贸易博览会,赋能数字经济新未来!
  • C#索引和范围:简化集合访问的现代特性详解
  • 2025年 UI 自动化框架使用排行
  • 深度模型结构选择和应用分析
  • 多重性校正:临床试验统计的关键防线
  • 自由学习记录(65)
  • 【算法】动态规划:1137. 第 N 个泰波那契数
  • python训练打卡DAY40
  • 时序数据集---UWave
  • 《燕云十六声》全栈技术架构深度解析
  • docker搭建minio和python使用minio
  • Java web1(黑马)
  • 【知识图谱构建系列7】:结果评价(1)
  • K8s环境下基于Nginx WebDAV与TLS/SSL的文件上传下载部署指南
  • 【Java面试】如何解决MQ死信队列?
  • OpenCV CUDA模块设备层----计算向量的平方根函数sqrt
  • 使用nomachine远程连接ARM设备桌面
  • C# 字符串中‘$‘和‘@‘的使用
  • C++的特殊类
  • STM32——DAP下载程序和程序调试
  • (4)pytest-fixture
  • Go语言安装使用教程
  • 深度剖析 LNK 参数隐藏攻击 (ZDI-CAN-25373)
  • 【甲方安全建设】敏感数据检测工具 Earlybird 安装使用详细教程
  • 门控循环单元(GRU):LSTM 的轻量级高效 “记忆专家”
  • Instrct-GPT 强化学习奖励模型 Reward modeling 的训练过程原理实例化详解