1.任务
这一节主要的任务是解决文件的上传和下载功能
2.文件上传
概念:将本地的图片上传到浏览器上面
点击文件上传,前端就会发送如上的请求,服务端应该根据URL和请求方法来处理请求
CommonController类:
@RestController
@Slf4j
@RequestMapping("/common")
public class CommonController {
//将在配置文件中的路径参数赋给basePath
@Value("${reggie.path}")
private String basePath;
/**
* 文件上传
* @param file
* @return
*/
@PostMapping("/upload")
public R<String> upload (MultipartFile file){
//file是一个临时文件(上传文件之后会放在临时文件夹里)本次请求结束之后,文件就会删除
log.info(file.toString());
//获取原始文件名
String originalFilename = file.getOriginalFilename();
//将原始文件名后缀拿到
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
//使用UUID重新生成文件名并且拼接了后缀,为了防止重名
String fileName = UUID.randomUUID().toString() + suffix;
//如果存储路径不存在,则要先新建一个文件夹
//创建一个目录对象
File dir = new File(basePath);
if (!dir.exists()){
dir.mkdir();
}
//将文件存储在指定位置(防止临时文件删除)
try {
//basePath:存储路径
//filename:文件名加后缀
file.transferTo(new File(basePath+fileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
//为什么返回文件名,因为当添加菜品的时候,我们需要把图片也存到菜品的表里,所以要知道文件名
return R.success(fileName);
}
}
前端input标签:
application.properties:
reggie.path=E:/springbootPicture/
分三个部分来介绍上面的代码
- 首先是要接收前端传过来的文件,这里springmvc给我们提供了一个文件处理类MultipartFile,参数名这里由于是前端input标签里指定的name为file,所以参数名也必须是file
- 当服务端接收到前端传来的图片之后,会把图片存放在临时文件中,当这个请求结束后,图片就会删除,所以接下来应该做的就是把图片存放在我们指定的目录下。这里的文件目录是放在了application.properties配置文件中了,然后在controller层中用@Value注解引入
- 最后一步做了一个简单的判断,如果本地没有指定的文件目录,则就生成该目录,反之,就直接将获取的文件存放在该目录下
3.文件下载
前端页面先发送请求,然后服务端再通过输出流的方式,把它写回到浏览器页面,这样就能实现文件(图片)的展现
当把图片上传之后,浏览器立马就会再次发送请求,路径里会把图片的name发送过来
/**
*
* @param name 获取文件名
* @param response 来操作流
*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response){
try {
//输入流(读取文件内容)
FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));
//输出流(将文件写回浏览器,在浏览器展示图片)
//这里不new一个输出流,而是用response来get一个输出流,因为要返回给浏览器
ServletOutputStream outputStream = response.getOutputStream();
//设置响应类型(类型为图片)
response.setContentType("image/jpeg");
//通过输入流来读取文件
byte[] bytes = new byte[1024];
int length = 0;
//如果length不为-1表示还没有读完,则一边读一边写
while((length = fileInputStream.read(bytes)) != -1) {
//向浏览器写文件内容,从0开始写到length为止
outputStream.write(bytes,0,length);
}
//关闭资源
fileInputStream.close();
outputStream.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
上面的方法主要有以下几步:
- new一个输入流,读取文件内容
- 用response创建输出流,将文件写回浏览器
- 关闭输入和输出流