前端部分

若依已经封装好了图片和文件上传组件,参照官方文档使用就行

1. 图片上传

    <template><div class="component-upload-image"><el-uploadmultiple:action="uploadImgUrl"list-type="picture-card":on-success="handleUploadSuccess":before-upload="handleBeforeUpload":limit="limit":on-error="handleUploadError":on-exceed="handleExceed"name="file":on-remove="handleRemove":show-file-list="true":headers="headers":file-list="fileList":on-preview="handlePictureCardPreview":class="{hide: this.fileList.length >= this.limit}"><i class="el-icon-plus"></i></el-upload><!-- 上传提示 --><div class="el-upload__tip" slot="tip" v-if="showTip">请上传<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template><template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>的文件</div><el-dialog:visible.sync="dialogVisible"title="预览"width="800"append-to-body><img:src="dialogImageUrl"style="display: block; max-width: 100%; margin: 0 auto"/></el-dialog></div>
</template><script>
import { getToken } from "@/utils/auth";export default {props: {value: [String, Object, Array],// 图片数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 5,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ["png", "jpg", "jpeg"],},// 是否显示提示isShowTip: {type: Boolean,default: true}},data() {return {number: 0,uploadList: [],dialogImageUrl: "",dialogVisible: false,hideUpload: false,baseUrl: process.env.VUE_APP_BASE_API,uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址headers: {Authorization: "Bearer " + getToken(),},fileList: []};},watch: {value: {handler(val) {if (val) {// 首先将值转为数组const list = Array.isArray(val) ? val : this.value.split(',');// 然后将数组转为对象数组this.fileList = list.map(item => {if (typeof item === "string") {if (item.indexOf(this.baseUrl) === -1) {item = { name: this.baseUrl + item, url: this.baseUrl + item };} else {item = { name: item, url: item };}}return item;});} else {this.fileList = [];return [];}},deep: true,immediate: true}},computed: {// 是否显示提示showTip() {return this.isShowTip && (this.fileType || this.fileSize);},},methods: {// 删除图片handleRemove(file, fileList) {const findex = this.fileList.map(f => f.name).indexOf(file.name);if(findex > -1) {this.fileList.splice(findex, 1);this.$emit("input", this.listToString(this.fileList));}},// 上传成功回调handleUploadSuccess(res) {this.uploadList.push({ name: res.fileName, url: res.fileName });if (this.uploadList.length === this.number) {this.fileList = this.fileList.concat(this.uploadList);this.uploadList = [];this.number = 0;this.$emit("input", this.listToString(this.fileList));this.$modal.closeLoading();}},// 上传前loading加载handleBeforeUpload(file) {let isImg = false;if (this.fileType.length) {let fileExtension = "";if (file.name.lastIndexOf(".") > -1) {fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);}isImg = this.fileType.some(type => {if (file.type.indexOf(type) > -1) return true;if (fileExtension && fileExtension.indexOf(type) > -1) return true;return false;});} else {isImg = file.type.indexOf("image") > -1;}if (!isImg) {this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`);return false;}if (this.fileSize) {const isLt = file.size / 1024 / 1024 < this.fileSize;if (!isLt) {this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);return false;}}this.$modal.loading("正在上传图片,请稍候...");this.number++;},// 文件个数超出handleExceed() {this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);},// 上传失败handleUploadError() {this.$modal.msgError("上传图片失败,请重试");this.$modal.closeLoading();},// 预览handlePictureCardPreview(file) {this.dialogImageUrl = file.url;this.dialogVisible = true;},// 对象转成指定字符串分隔listToString(list, separator) {let strs = "";separator = separator || ",";for (let i in list) {strs += list[i].url.replace(this.baseUrl, "") + separator;}return strs != '' ? strs.substr(0, strs.length - 1) : '';}}
};
</script>
<style scoped lang="scss">
// .el-upload--picture-card 控制加号部分
::v-deep.hide .el-upload--picture-card {display: none;
}
// 去掉动画效果
::v-deep .el-list-enter-active,
::v-deep .el-list-leave-active {transition: all 0s;
}::v-deep .el-list-enter, .el-list-leave-active {opacity: 0;transform: translateY(0);
}
</style>

2.文件上传

<template><div class="upload-file"><el-uploadmultiple:action="uploadFileUrl":before-upload="handleBeforeUpload":file-list="fileList":limit="limit":on-error="handleUploadError":on-exceed="handleExceed":on-success="handleUploadSuccess":show-file-list="false":headers="headers"class="upload-file-uploader"ref="upload"><!-- 上传按钮 --><el-button size="mini" type="primary">选取文件</el-button><!-- 上传提示 --><div class="el-upload__tip" slot="tip" v-if="showTip">请上传<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template><template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>的文件</div></el-upload><!-- 文件列表 --><transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"><li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"><el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank"><span class="el-icon-document"> {{ getFileName(file.name) }} </span></el-link><div class="ele-upload-list__item-content-action"><el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link></div></li></transition-group></div>
</template><script>
import { getToken } from "@/utils/auth";export default {name: "FileUpload",props: {// 值value: [String, Object, Array],// 数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 5,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ["doc", "xls", "ppt", "txt", "pdf"],},// 是否显示提示isShowTip: {type: Boolean,default: true}},data() {return {number: 0,uploadList: [],baseUrl: process.env.VUE_APP_BASE_API,uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址headers: {Authorization: "Bearer " + getToken(),},fileList: [],};},watch: {value: {handler(val) {if (val) {let temp = 1;// 首先将值转为数组const list = Array.isArray(val) ? val : this.value.split(',');// 然后将数组转为对象数组this.fileList = list.map(item => {if (typeof item === "string") {item = { name: item, url: item };}item.uid = item.uid || new Date().getTime() + temp++;return item;});} else {this.fileList = [];return [];}},deep: true,immediate: true}},computed: {// 是否显示提示showTip() {return this.isShowTip && (this.fileType || this.fileSize);},},methods: {// 上传前校检格式和大小handleBeforeUpload(file) {// 校检文件类型if (this.fileType) {let fileExtension = "";if (file.name.lastIndexOf(".") > -1) {fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);}const isTypeOk = this.fileType.some((type) => {if (file.type.indexOf(type) > -1) return true;if (fileExtension && fileExtension.indexOf(type) > -1) return true;return false;});if (!isTypeOk) {this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);return false;}}// 校检文件大小if (this.fileSize) {const isLt = file.size / 1024 / 1024 < this.fileSize;if (!isLt) {this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);return false;}}this.$modal.loading("正在上传文件,请稍候...");this.number++;return true;},// 文件个数超出handleExceed() {this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);},// 上传失败handleUploadError(err) {this.$modal.msgError("上传图片失败,请重试");this.$modal.closeLoading()},// 上传成功回调handleUploadSuccess(res) {this.uploadList.push({ name: res.fileName, url: res.fileName });if (this.uploadList.length === this.number) {this.fileList = this.fileList.concat(this.uploadList);this.uploadList = [];this.number = 0;this.$emit("input", this.listToString(this.fileList));this.$modal.closeLoading();}},// 删除文件handleDelete(index) {this.fileList.splice(index, 1);this.$emit("input", this.listToString(this.fileList));},// 获取文件名称getFileName(name) {if (name.lastIndexOf("/") > -1) {return name.slice(name.lastIndexOf("/") + 1);} else {return "";}},// 对象转成指定字符串分隔listToString(list, separator) {let strs = "";separator = separator || ",";for (let i in list) {strs += list[i].url + separator;}return strs != '' ? strs.substr(0, strs.length - 1) : '';}}
};
</script><style scoped lang="scss">
.upload-file-uploader {margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {border: 1px solid #e4e7ed;line-height: 2;margin-bottom: 10px;position: relative;
}
.upload-file-list .ele-upload-list__item-content {display: flex;justify-content: space-between;align-items: center;color: inherit;
}
.ele-upload-list__item-content-action .el-link {margin-right: 10px;
}
</style>

process.env.VUE_APP_BASE_API 来自.env.development文件,用于区分多环境

后端部分

其中涉及的工具类大家可以下载若依开源项目获取,这里只梳理思路

1.文件上传

需要将附件信息返回到前端,随前端表单一起提交,提交过程中先保存表单信息,获取到相关记录主键id,然后将附件信息和主键id一起存到附件表

    /***  上传附件* @author Milo Lee* @date 2022/5/31 17:44* @param file 文件* @param cuDir 目录* @return com.sjft.common.model.ResultBody<com.sjft.file.client.model.entity.FileUploadRecord>*/@PostMapping(value = "/common/upload")public ResultBody<FileUploadRecord> upload(MultipartFile file, @RequestParam("curDir")String cuDir) {//改变文件名称,如果容器选用undertow,需要此操作MultipartFile file1 = FileUtils.changeFileName(file, "fileName");String name = null;try {name = FileUploadUtils.upload(pathUpload + cuDir, file1);} catch (IOException e) {e.printStackTrace();}//组装返回信息String url = domain + filePrefix   + name;FileUploadRecord fileAttachment = new FileUploadRecord();//上传时间fileAttachment.setCreateTime(DateUtil.date());//访问url[通过nginx代理,实现访问]fileAttachment.setUrl(url);//文件保存名[用于下载]fileAttachment.setSaveName(name);return ResultBody.ok().data(fileAttachment);}

2.通用下载

一般在涉及到模块下载这类功能,直接使用通用下载,在存储路径下面新建download文件夹,下载路径=磁盘基础路径+文件名,直接可以定位文件,进行下载

    /*** 通用下载请求* @param fileName 文件名称* @param delete 是否删除*/@GetMapping("common/download")public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {try {if (!FileUtils.isValidFilename(fileName)) {throw new Exception("文件名称非法,不允许下载。"+fileName);}String realFileName = fileName.substring(fileName.indexOf("_") + 1);//这一步,pathDownLoad就是磁盘存储路径前缀,fileName就是文件名称String filePath = pathDownLoad + fileName;response.setCharacterEncoding("utf-8");response.setContentType("multipart/form-data");response.setHeader("Content-Disposition","attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));FileUtils.writeBytes(filePath, response.getOutputStream());if (delete) {FileUtils.deleteFile(filePath);}} catch (Exception e) {log.error("下载文件失败", e);}}

3. 普通下载

    /*** 文件下载请求* @author Milo Lee* @date 2022/5/28 10:41*/@GetMapping("/common/download/resource")public  void resourceDownload(String url, HttpServletRequest request, HttpServletResponse response) throws Exception{// 文件上传base路径String localPath = pathUpload;// 下面两步就是将访问url转换为文件在磁盘的存储路径String downloadPath = localPath + substringAfter(url, "profile");// 下载名称String downloadName = substringAfterLast(downloadPath, "/");response.setCharacterEncoding("utf-8");response.setContentType("multipart/form-data");response.setHeader("Content-Disposition","attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));FileUtils.writeBytes(downloadPath, response.getOutputStream());}public   String substringAfter(String str, String separator) {if (StrUtil.isEmpty(str)) {return str;} else if (separator == null) {return "";} else {int pos = str.indexOf(separator);return pos == -1 ? "" : str.substring(pos + separator.length());}}public  String substringAfterLast(String str, String separator) {if (StrUtil.isEmpty(str)) {return str;} else if (StrUtil.isEmpty(separator)) {return "";} else {int pos = str.lastIndexOf(separator);return pos != -1 && pos != str.length() - separator.length() ? str.substring(pos + separator.length()) : "";}}

闲来无事,探究一番若依框架文件上传下载实现原理相关推荐

  1. struts上传word和excel文件到oracle,Struts文件上传,下载,重传,预览

    [Struts2]☆★之文件上传,下载,重传,预览 今日群里一兄弟问我能否给一份struts文件上传下载的例子,因为自己项目比较紧所以想在网上找 些源码给他,但是纵观全网,写的都不是太全,这让新手使用 ...

  2. 文件上传 java web_JavaWeb 文件上传下载

    1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端,从服务器端下载文件到本地的过程.例如目前网站需要上传头像.上传下载图片或网盘等功能都是利用文件上传下 ...

  3. 关于SpringMVC框架实现简单的文件上传下载(ssm)

    关于ssm框架整合文件的上传和下载. 首先来看单个附件的上传和下载: 1.首先创建一个用来测试的jsp文件上传下载的页面  代码如下 <%@ page language="java&q ...

  4. Jersey框架:文件上传下载

    企业应用中,文件管理是非常通用和重要的模块,功能包括文件上传.下载.文件管理(浏览.删除.权限等)等操作,本文针对Jersey框架实现文件的上传和下载. Jersey文件特性 Jersey实现文件上传 ...

  5. ASP.NET中常用的文件上传下载方法

    ASP.NET中常用的文件上传下载方法 文件的上传下载是我们在实际项目开发过程中经常需要用到的技术,这里给出几种常见的方法,本文主要内容包括: 1.如何解决文件上传大小的限制 2.以文件形式保存到服务 ...

  6. android 文件上传工具类,Android快速开发架构PlanA(五),文件上传下载了解一下...

    1.PlanA文件上传&下载的使用 PlanA架构集成第五篇,文件上传下载的使用,文件上传&下载在APP里面随处可见,发朋友圈要上传图片或者短视频,换个头像要上传选择的图片,offic ...

  7. 【SpringMVC笔记】拦截器 + 文件上传下载

    拦截器 + 文件上传下载 拦截器(interceptor) 自定义拦截器 验证用户是否登录 (认证用户) 没有拦截器 配置拦截器 文件的上传 文件输出流进行文件上传 file.Transto 进行文件 ...

  8. JSON+AJAX+ThreadLocal+文件上传下载

    文章目录 JSON和AJAX文档介绍 1. JSON介绍 1.1 JSON快速入门 1.2 JSON和字符串转换 1.2.1 JSON转字符串 1.2.2 字符串转JSON 1.2.3 JSON和字符 ...

  9. SB_5_瑞吉外卖_4_文件上传下载_菜品新增_菜品分页查询_菜品修改

    瑞吉外卖-Day04 课程内容 文件上传下载 菜品新增 菜品分页查询 菜品修改 1. 文件上传下载 1.1 上传介绍 1.1.1 概述 文件上传,也称为upload,是指将本地图片.视频.音频等文件上 ...

最新文章

  1. 解决dell poweredge 2850 服务器系统内存限制
  2. SAP零售行业解决方案初阶 1
  3. 计算机游戏与动漫设计大赛,我院获第10届中国大学生计算机设计大赛 数字媒体设计类动漫游戏组一等奖...
  4. REMOTE HOST IDENTIFICATION HAS CHANGED
  5. 给插店一个成功案例给自己一次机会
  6. mockito手动注入依赖_依赖注入–手动方式
  7. 高可用性、负载均衡的mysql集群解决方案
  8. 软考【网络工程师】(上午经典例题——软件项目活动图 详解)
  9. 廊坊交警利用智能交通管控平台助力平安建设工作
  10. 新生周赛——YZJ的牛肉干
  11. vb.net下打印清单示例(连续纸和固定纸张打印)
  12. 湖南师范大学2018年大学生程序设计竞赛新生赛 F 小名的回答
  13. 聪明人为何无法征服世界?
  14. 怎么建立设备管理系统?
  15. Mac无法打开应用,安装来源不明,不受信任的一种解决方法
  16. 圣思园——Java SE Lesson 5
  17. 清华计算机系开学典礼,清华大学举行2017级本科生新生开学典礼
  18. 嗅探路由器PPPOE拨号密码
  19. C++入口函数main返回值
  20. MFC手动添加窗口 最大化 最小化 还原 关闭

热门文章

  1. [转]NoSQL数据库笔谈
  2. 【FPGA】MicroBlaze小试01-串口输出Hello World(demo,熟悉开发流程)
  3. 为知笔记,Ulysses和Effie哪个更适合公众号主?
  4. 制作html5移动端页面,移动端H5页面制作规范
  5. “PDF修改器 2.5.2.0[强大的免费PDF文件编辑软件]”乃是假冒软件
  6. java毕业设计网上书城网站mybatis+源码+调试部署+系统+数据库+lw
  7. linux usb 摄像头测试软件
  8. 【掌控板】0、基础教程
  9. 【Web实战-Tomcat-Servlet-Thymeleaf -JDBC-MySQL】浏览器页面显示数据库数据(水果库存系统)
  10. VirtualBox虚拟网络环境配置【两台虚拟机互通】