文件上传与下载
在Spring Boot中实现文件上传与下载的功能通常涉及前端和后端的交互。前端负责提供文件选择的界面和触发上传/下载操作,后端则负责处理文件上传的请求、存储文件,以及处理文件下载的请求并发送文件内容给前端。
文件上传
- 前端:使用HTML表单或JavaScript库来选择文件并发送POST请求到后端。
- 后端:在Spring Boot中,你可以使用MultipartFile接口来处理文件上传。下面是一个简单的示例。
前端
<div class="container">
<h1 class="title">文件上传</h1>
<form action="/uploadFile" enctype="multipart/form-data" method="post">
<div class="upload-area">
<input type="file" id="fileInput" name="files"
multiple onchange="updateFileList(this)">
<button type="submit" >上传文件</button>
</div>
<ul id="fileList" class="file-list"></ul>
</form>
<p id="uploadSuccess" class="upload-success"
th:text="${uploadStatus}">文件上传成功!</p>
</div>
后端Controller示例:
实体表
@Data
@TableName("attachment")
public class Attachment {
@TableId(type = IdType.AUTO)
private Long id;
private String fileName;
private String storagePath;
}
上传页面访问方法
@Controller
public class FileController {
@Autowired
private IAttachmentService attachmentService;
// 向文件上传页面跳转
@GetMapping("/toUpload")
public String upload(){
return "upload";
}
}
文件上传方法
//文件上传管理
@PostMapping("/uploadFile")
public String uploadFile(MultipartFile[] files, Model model){
// 默认文件上传成功,并返回状态信息
model.addAttribute("uploadStatus", "上传成功!");
for(MultipartFile file:files){
// 获取文件名以及后缀名
String fileName = file.getOriginalFilename();
// 重新生成文件名(根据具体情况生成对应文件名)
fileName = UUID.randomUUID()+"_"+fileName;
// 指定上传文件本地存储目录,不存在需要提前创建
String dirPath = "D:/file/";
File filePath = new File(dirPath);
if(!filePath.exists()){
filePath.mkdirs();
}
try {
file.transferTo(new File(dirPath+fileName));
//文件信息存储到数据库中
Attachment attachment = new Attachment();
attachment.setFileName(file.getOriginalFilename());
attachment.setStoragePath(fileName);
attachmentService.save(attachment);
} catch (Exception e) {
e.printStackTrace();
// 上传失败,返回失败信息
model.addAttribute("uploadStatus","上传失败: "+e.getMessage());
}
}
// 携带上传状态信息回调到文件上传页面
return "upload";
}
文件下载
前端:用户点击下载链接或按钮,触发GET请求到后端。
后端:在后端Controller中处理GET请求,读取文件内容,并将其作为HTTP响应返回给前端。
前端
<h1>文件下载列表</h1>
<div class="file-list" >
<div class="file-item" th:each="attachment:${list}">
<p class="file-name" th:text="${attachment.fileName}">文件名1</p>
<a th:href="${'/download?id='+attachment.id}"
class="download-button" download>下载</a>
</div>
<!-- 添加更多文件项 -->
</div>
下载页面访问方法
/**
* 向文件下载页面跳转
*/
@GetMapping("/toDownload")
public String toDownload(Model model){
//查询文件信息
List<Attachment> list = attachmentService.list();
model.addAttribute("list",list);
return "download";
}
文件下载方法
// 文件下载
@GetMapping("/download")
public ResponseEntity<Resource> fileDownload(HttpServletRequest request,Long id)
throws Exception{
//获取文件数据对象
Attachment attachment = attachmentService.getById(id);
// 指定要下载的文件根路径
String dirPath = "D:/file/";
// 创建该文件对象
File file = new File(dirPath + attachment.getStoragePath());
// 设置响应头
HttpHeaders headers = new HttpHeaders();
// 通知浏览器以下载方式打开(下载前对文件名进行转码)
String filename=getFilename(request,attachment.getFileName());
headers.setContentDispositionFormData("attachment",filename);
// 定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
InputStreamResource inputStreamResource =
new InputStreamResource(Files.newInputStream(file.toPath()));
return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);
}
文件名乱码处理方法
// 根据浏览器的不同进行编码设置,返回编码后的文件名
private String getFilename(HttpServletRequest request, String filename)
throws Exception {
// IE不同版本User-Agent中出现的关键词
String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
// 获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
for (String keyWord : IEBrowserKeyWords) {
if (userAgent.contains(keyWord)) {
//IE内核浏览器,统一为UTF-8编码显示,并对转换的+进行更正
return URLEncoder.encode(filename, "UTF-8").replace("+"," ");
}
}
//火狐等其它浏览器统一为ISO-8859-1编码显示
return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
}
效果测试
文件上传
文件下载页面