Springboot——文件的上传与下载(reggie)
目录
一、文件上传——upload
1.1 介绍
1.2 前端代码实现
1.3 后端代码实现
二、文件下载——download
2.1 介绍
2.2 前端代码编写
2.3 后端代码编写
三、 前端总代码
一、文件上传——upload
1.1 介绍
将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程
文件上传时,对页面的form表单有如下要求:
- method="post" 采用post方式提交数据
- encttype=""multipart/form-data" 采用multipart格式上传文件
- type="file" 使用input的file空间上传
服务端接收客户端页面上传的文件时,通常会使用Apache的两个组件:
- commons-fileupload
- commons-io (对文件的操作本质上还是对流的操作)
Spring框架在sprin-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在Controller方法中声明一个MultipartFile类型的参数即可接收上传的文件
1.2 前端代码实现
使用的element-ui组件进行实现,这段代码的编写既有上传,也有下载,其中:src就是下载图片
<el-upload class="avatar-uploader"action="/common/upload":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeUpload"ref="upload"><img v-if="imageUrl" :src="imageUrl" class="avatar"></img><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload>
- action="/common/upload" 代表controller层的请求路径
1.3 后端代码实现
我们可以先发一个请求查看一下MultipartFile对象里面包括什么
我们仔细看发现了一个存储路径,也就是说当前传过来的文件被存储在了一个临时的位置(临时目录),我们要做的就是把这个文件存储到一个指定的位置。如果不转存的话,当我们此次请求结束后,这个文件就不存在了。
我们在请求成功后返回了图片的文件名+后缀名,目的就是为了下载图片的时候将图片名称传过去然后找到对应的图片
/* 文件的上传和下载*/
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {@Value("${reggie.path}")private String basePath;/* 文件上传 @param file 是一个临时文件,需要转存的指定的位置,否则本次请求后此文件就会消失* @return*/@PostMapping("/upload")public R<String> upload(MultipartFile file) throws IOException {log.info("上传文件:{}", file.toString());// 1.拼接转存的位置
// 获取文件的原始名String originalFilename = file.getOriginalFilename(); //abc.jpg
// 文件名后缀String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));// 也可以使用UUID生成文件名,防止文件名称重复导致覆盖原文件String filename = UUID.randomUUID().toString(); //缺少后缀String url= basePath + filename+suffix;// 2. 判断转存的目录是否存在
// File既可以代表一个目录,又可以代表一个文件File dir = new File(basePath);
// 判断当前目录是否存在if (!dir.exists()){
// 不存在的时候进行创建dir.mkdirs();}// 转存临时文件到指定的位置 参数是一个URL路径file.transferTo(new File(url));return R.success(filename+suffix);}}
二、文件下载——download
2.1 介绍
指将文件从服务器传输到本地计算机的过程。
通过浏览器进行文件下载,通常有两种表现形式:
- 以附件形式下载,弹出保存对话框,将文件保存到指定磁盘目录
- 直接在浏览器中打开
通过浏览器进行文件下载,本质上就是服务端将文件以流的形式写会浏览器的过程。
2.2 前端代码编写
<img v-if="imageUrl" :src="imageUrl" class="avatar"></img>
2.3 后端代码编写
/* 文件下载 @param name 图片名* @param response 图片要通过响应流获得*/@GetMapping("/download")public void download(String name, HttpServletResponse response) throws IOException {
// 0. 设置文件格式response.setContentType("image/jpeg");// 1. 输入流,通过输入流读取文件内容FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));// 2. response输出流,将文件写回浏览器ServletOutputStream outputStream = response.getOutputStream();int len = 0;byte[] bytes = new byte[1024];while ((len = fileInputStream.read(bytes)) != -1) {outputStream.write(bytes, 0, len);outputStream.flush();}// 3.关闭流outputStream.close();fileInputStream.close();}
三、 前端总代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传</title><!-- 引入样式 --><link rel="stylesheet" href="../../plugins/element-ui/index.css" /><link rel="stylesheet" href="../../styles/common.css" /><link rel="stylesheet" href="../../styles/page.css" />
</head>
<body><div class="addBrand-container" id="food-add-app"><div class="container"><el-upload class="avatar-uploader"action="/common/upload":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeUpload"ref="upload"><img v-if="imageUrl" :src="imageUrl" class="avatar"></img><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></div></div><!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="../../plugins/vue/vue.js"></script><!-- 引入组件库 --><script src="../../plugins/element-ui/index.js"></script><!-- 引入axios --><script src="../../plugins/axios/axios.min.js"></script><script src="../../js/index.js"></script><script>new Vue({el: '#food-add-app',data() {return {imageUrl: ''}},methods: {handleAvatarSuccess (response, file, fileList) {this.imageUrl = `/common/download?name=${response.data}`},beforeUpload (file) {if(file){const suffix = file.name.split('.')[1]const size = file.size / 1024 / 1024 < 2if(['png','jpeg','jpg'].indexOf(suffix) < 0){this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')this.$refs.upload.clearFiles()return false}if(!size){this.$message.error('上传文件大小不能超过 2MB!')return false}return file}}}})</script>
</body>
</html>