您现在的位置是:首页 >其他 >瑞吉外卖 - 文件上传与下载功能(15)网站首页其他
瑞吉外卖 - 文件上传与下载功能(15)
某马瑞吉外卖单体架构项目完整开发文档,基于 Spring Boot 2.7.11 + JDK 11。预计 5 月 20 日前更新完成,有需要的胖友记得一键三连,关注主页 “瑞吉外卖” 专栏获取最新文章。
相关资料:https://pan.baidu.com/s/1rO1Vytcp67mcw-PDe_7uIg?pwd=x548
提取码:x548
1.文件上传介绍
文件上传,也称为 upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。
文件上传时,对页面的 form 表单通常有如下要求:
method="post"
:采用 POST 方式提交数据;enctype="multipart/form-data"
:采用 multipart 格式上传文件;type="file"
:使用 input 的 file 控件上传。
下面是一个简单例子:
<form method="post" action="/common/upload" enctype=="multipart/form-data">
<input name="myFile" type="file"/>
<input type="submit" value="提交"/>
</form>
目前一些前端组件库也提供了相应的上传组件,但是底层原理还是基于 form 表单的文件上传。例如 Element Ul 中提供的 upload 上传组件:
服务端要接收客户端页面上传的文件,通常都会使用 Apache 的两个组件:
- commons-fileupload
- commons-io
可是直接使用 Apache 的两个组件进行开发有些繁琐,Spring 框架在 spring-web 包中基于 Apache 的两个组件对文件上传进行了封装,大大简化了服务端代码,我们只需要在 Controller 的方法中声明一个 MultipartFile
类型的参数即可接收上传的文件,例如:
@PostMapping("/upload")
public R<String> upload(MultipartFile file){
......
}
2.文件下载介绍
文件下载,也称为 download,是指将文件从服务器传输到本地计算机的过程。通过浏览器进行文件下载,通常有两种表现形式:
- 以附件形式下载,弹出保存对话框,将文件保存到指定磁盘目录;
- 直接在浏览器中打开。
通过浏览器进行文件下载,本质上就是服务端将文件以流的形式写回浏览器的过程。
3.文件上传代码实现
对于文件上传,页面端可以使用 Element UI 提供的上传组件。可以直接使用下载的资料中提供的上传页面:
位置:瑞吉外卖瑞吉外卖项目资料文件上传下载页面upload.html
直接将 upload.html 复制到项目的 static/backend/page/demo/upload.html
路径下即可,需要处理的请求信息如下:
我们新建一个 controller/CommonController.java
类用于处理文件上传与下载相关的公共类,文件上传代码如下:
package cn.javgo.reggie_take_out.controller;
import cn.javgo.reggie_take_out.common.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.UUID;
/**
* 处理文件上传下载的控制器
*/
@RestController
@RequestMapping("/common")
public class CommonController {
@Value("${reggie.upload-path}")
private String uploadPath;
/**
* 文件上传
* 说明:
* 1.前端的 form 表单必须指定 enctype="multipart/form-data" 属性
* 2.前端的 input 标签必须指定 name 属性,后端通过 name 属性获取文件
* 3.file 是一个临时文件,上传成功后会自动删除,因此需要将文件拷贝到指定目录
*
* @param file 文件,必须与前端的 name 属性一致
* @return R
*/
@PostMapping("/upload")
public R<String> upload(MultipartFile file){
// 1.获取原始文件名
String fileName = file.getOriginalFilename();
// 2.截取文件扩展名
String suffix = fileName.substring(fileName.lastIndexOf("."));
// 3.使用 UUID 生成文件名,防止重复
String newFileName = UUID.randomUUID().toString() + suffix;
// 4.创建文件对象
File dir = new File(uploadPath);
// 5.判断目录是否存在,不存在则创建
if(!dir.exists()){
dir.mkdirs();
}
// 6.将文件写入磁盘
try {
file.transferTo(new File(uploadPath + newFileName));
} catch (Exception e) {
e.printStackTrace();
}
// 7.返回文件名,用于回显
return R.success(newFileName);
}
}
注释比较明确,就不一一展开说明了,上面需要注意的是代表文件对象的 MultipartFile
参数名必须与前端 input
标签的 name
属性一致:
上述代码中为了灵活配置文件保存位置,我们将存储路径配置到了 application 配置文件中,然后使用 @Value("${reggie.upload-path}")
进行注入,配置内容如下:
# reggie 相关配置
reggie:
upload-path: D: est
eggiefile
重启应用,登陆后再访问 http://localhost:8080/backend/page/demo/upload.html 页面进行上传测试:
查看对应保存位置,图片上传成功:
4.文件下载代码实现
在我们成功上传文件后,就会涉及到一个文件下载的问题,这样才能够实现上传成功后能够在页面看到刚才上传的图片,对应需要处理的请求信息如下:
对应的处理方法如下:
@RestController
@RequestMapping("/common")
public class CommonController {
/**
* 文件下载
* @param name 文件名
* @param response 响应对象
*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response){
// 1.创建文件对象
File file = new File(uploadPath + name);
// 2.判断文件是否存在
if (file.exists()){
try{
// 3.使用输入流读取文件
FileInputStream fis = new FileInputStream(file);
// 4.使用输出流将文件写出
ServletOutputStream sos = response.getOutputStream();
// 5.设置响应类型为图片类型
response.setContentType("image/jpeg");
// 6.定义一个长度变量,用于存放每次读取的数据长度
int len = 0;
// 7.定义一个 1024 字节的缓冲区,用于存放每次读取的数据
byte[] buffer = new byte[1024];
// 8.循环将输入流中的数据读取到缓冲区中,(len = fis.read(buffer)) > 0 表示读取到数据
while ((len = fis.read(buffer)) != -1){
// 9.使用输出流将缓冲区的数据输出到客户端浏览器
sos.write(buffer,0,len);
// 10.刷新输出流
sos.flush();
}
// 11.关闭资源
sos.close();
fis.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
// 省略其他方法
}
实现思路中规中矩,这里就不再进行解释了,看注释即可。下面重启应用再次进行图片上传测试(先登录后访问上传页面),上传完成后随后执行下载图片进行回显: