这篇文章记录我自己的学习过程的SpringBoot的文件上传下载的代码的理解
1.文件上传
首先先把代码写上,然后逐一理解
@RestController
@RequestMapping("/files")
public class FileController {
//文件上传存储路径
private static final String filepath=System.getProperty("user.dir")+"/files";//System.getProperty("user.dir")为当前用户路径
@Value("9093")
private String port;
@Value("localhost")
private String ip;
/**
* 文件上传
*/
@PostMapping("/upload")
public Result upload(MultipartFile file) {
String flag;
synchronized (FileController.class){
flag=System.currentTimeMillis()+"";//获取当前时间戳
ThreadUtil.sleep(1L);//线程休眠1毫秒
}
String filename=file.getOriginalFilename();//获取文件名
try{
if (!FileUtil.isDirectory(filepath)){
FileUtil.mkdir(filepath);
}
FileUtil.writeBytes(file.getBytes(),filepath+"/"+flag+"-"+filename);//写入文件
System.out.println(filename+"文件上传成功");
}catch (Exception e){
System.out.println(filename+"文件上传失败");
}
String http="http://"+ip+":"+port+"/files/";
return Result.success(http+flag+"-"+filename);
}
文件接口不多说了
首先理解一下文件上传的原理,其实就是把传过来的文件存到我们的磁盘上,既然要存磁盘所以我们得指定文件存储的路径等
private static final String filepath=System.getProperty("user.dir")+"/files";
这段代码就filepath是指定文件的存储路径
System.getProperty("user.dir")这个指的是当前用户路径,拿我的路径举例看下图
我的路径值得就是这个self,后面+"/files",指的就是self/files这个文件夹
@Value("9093") private String port; @Value("localhost") private String ip;
这个代码不多说了,定义接口及ip地址
String flag; synchronized (FileController.class){ flag=System.currentTimeMillis()+"";//获取当前时间戳 ThreadUtil.sleep(1L);//线程休眠1毫秒 }
定义flag获取当前时间戳是为了给文件一个唯一的标识,这里加锁是为了避免在多线程下并发的问题,休眠一毫秒对性能没什么影响
String filename=file.getOriginalFilename(); 这是获取文件名
try{ if (!FileUtil.isDirectory(filepath)){ FileUtil.mkdir(filepath); } FileUtil.writeBytes(file.getBytes(),filepath+"/"+flag+"-"+filename);//写入文件 System.out.println(filename+"文件上传成功"); }catch (Exception e){ System.out.println(filename+"文件上传失败"); }
这段代码中if (!FileUtil.isDirectory(filepath)){ FileUtil.mkdir(filepath); 是判断你的目录中有没有你定义的文件存储路径中那个文件夹,也就是files这个文件夹,如果没有的话会自动创建
FileUtil.writeBytes(file.getBytes(),filepath+"-"+flag+"-"+filename);//写入文件
这就是把文件写入到你定义的路径中,flag是你定义的时间戳,filename你的文件名这样组合起来那我这个举例
前面这串数字就是flag,1.jpg是filename
String http="http://"+ip+":"+port+"/files/";
return Result.success(http+flag+"-"+filename);
这段代码返回的是你的文件下载的路径,就像这样
http://localhost:9093/files/1711721550492-1.jpg
代码写完了介绍问了,接下来测试一下看看我们的接口能不能用
测试上传接口
我这里用apipost测试
控制台
文件夹下
可以看到上传成功了,也生成了文件名
介绍完了上传的代码接下来看一下下载的代码
2.文件下载
先把代码拿上
@GetMapping("/{flag}")//获取文件
public void download(@PathVariable String flag, HttpServletResponse response){
OutputStream os;//输出流
try{
if (StrUtil.isNotEmpty(flag)){
// 在响应中添加一个头部,用于设置下载文件的名称。
// 这段代码特别处理了文件名的编码,以确保文件名在不同的字符集下的正确性。
response.addHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(flag,"UTF-8"));//设置文件名
/*
* 设置响应的内容类型为 "application/octet-stream"。
* 这一设置表明响应体将是一个二进制流,常用于表示无法被浏览器直接识别的文件或数据。
* 该方法不接受任何参数,也不会返回任何值。
*/
response.setContentType("application/octet-stream");
byte[] bytes=FileUtil.readBytes(filepath+"/"+flag);//读取文件
os=response.getOutputStream(); //获取输出流
os.write(bytes);
os.flush();//刷新输出流
os.close();
}
}catch (Exception e){
System.out.println("文件下载失败");
}
}
下载的原理其实就是根据你要下载的文件名看看我们的磁盘中有没有这个文件对比一下文件名字,如果有就下载,没有就下载失败
这里的flag 用于标识要下载的文件,比如1711721550492-1.jpg我这个就是个flag,其实就是下载的文件名
if (StrUtil.isNotEmpty(flag)){ // 在响应中添加一个头部,用于设置下载文件的名称。 // 这段代码特别处理了文件名的编码,以确保文件名在不同的字符集下的正确性。 response.addHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(flag,"UTF-8"));//设置文件名 /* * 设置响应的内容类型为 "application/octet-stream"。 * 这一设置表明响应体将是一个二进制流,常用于表示无法被浏览器直接识别的文件或数据。 * 该方法不接受任何参数,也不会返回任何值。 */ response.setContentType("application/octet-stream"); byte[] bytes=FileUtil.readBytes(filepath+"/"+flag);//读取文件 os=response.getOutputStream(); //获取输出流 os.write(bytes); os.flush();//刷新输出流 os.close(); }
这里是判断这个文件是否存在,存在的话就在响应中加上一个头部,设置下载的文件名,然后把响应体设置成二进制流,读取到文件后用输出流输出。
ok,那我们测试一下
测试下载接口
下载成功
文件的上传下载就记录到这里了,另外再补充一个删除文件的接口吧
3.删除接口
这个就比较简单了,还是直接给代码
@DeleteMapping("/{flag}")
public void delFile(@PathVariable String flag) {
FileUtil.del(filepath +"/" +flag);
System.out.println("删除文件" + flag + "成功");
}
相信这个都能看懂,接受一个参数flag,其实就是文件名,然后调用del方法删除
测试删除接口
测试一下
控制台
文件夹里空了
ok,这篇博客就记录到这里吧