前言
在项目开发中,我们往往需要用户上传、下载文件到服务器本地,那么我们的服务端如何接收、保存和下载文件呢?
一、引入pom文件
<!-- 文件传输 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
二、相关配置文件设置
spring:
servlet:
multipart:
#开启文件上传下载(默认开启)
enabled: true
#最大文件大小
max-file-size: 20MB
#单次最大文件大小
max-request-size: 20MB
#自定义配置
file:
upload:
#文件存放路径
dir: d:/
#文件不允许上传文件类型
unallow: exe,dll
三、配置文件注入
@ConfigurationProperties(prefix = "file.upload")
@Component
@Data
public class FileBean {
private String dir;
private String unallow;
}
四、具体操作
1、上传单个文件
@RestController
@RequiredArgsConstructor
@Slf4j
public class FileController {
private final FileBean fileBean;
@PostMapping("/uploadFile")
public Result fileUpload(@RequestParam("file") MultipartFile file) throws JSONException {
if (file.isEmpty()) return Result.fail("文件为空");
// 文件名
String fileName = file.getOriginalFilename();
String suffixName = fileName.substring(fileName.lastIndexOf("."));
log.info("上传文件名称为:{}, 后缀名为:{}", fileName, suffixName);
File fileTempObj = new File(fileBean.getDir() + File.separator + fileName);
// 检测目录是否存在
if (!fileTempObj.getParentFile().exists()) {
fileTempObj.getParentFile().mkdirs();
}
// 使用文件名称检测文件是否已经存在
if (fileTempObj.exists()) {
return Result.fail("文件已经存在");
}
try {
// 写入文件:方式1
// file.transferTo(fileTempObj);
// 写入文件:方式2(前提:导入hutool工具包)
FileUtil.writeBytes(file.getBytes(), fileTempObj);
} catch (Exception e) {
log.error("发生错误: {}", e);
return Result.fail(e.getMessage());
}
return Result.ok("文件上传成功");
}
}
2、上传多个文件
@PostMapping("/uploadFiles")
public Result fileUploads(@RequestParam("files") MultipartFile files[]) throws JSONException {
for (int i = 0; i < files.length; i++) {
String fileName = files[i].getOriginalFilename();
File dest = new File(fileBean.getDir() + File.separator + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
files[i].transferTo(dest);
} catch (Exception e) {
log.error("发生错误: {}", e);
return Result.fail(e.getMessage());
}
}
return Result.ok("文件上传成功");
}
3、文件下载
@GetMapping("/downloadFile")
public Result fileDownload(HttpServletResponse response, @RequestParam("fileName") String fileName) throws JSONException, IOException {
File file = new File(fileBean.getDir() + File.separator + fileName);
if (!file.exists()) {
return Result.fail("下载文件不存在!");
}
//设置响应信息
response.reset();
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//写入响应体中
// 原生的方式
// try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
// byte[] buff = new byte[1024];
// OutputStream os = response.getOutputStream();
// int i = 0;
// while ((i = bis.read(buff)) != -1) {
// os.write(buff, 0, i);
// os.flush();
// }
// } catch (IOException e) {
// log.error("发生错误: {}", e);
// result.put("error", e.getMessage());
// return result.toString();
// }
// 简单方式: 方式1(前提:引入hutool)
// byte[] bytes = FileCopyUtils.copyToByteArray(file);
// 简单方式: 方式2(前提:引入hutool)
byte[] readBytes = FileUtil.readBytes(file);
OutputStream os = response.getOutputStream();
os.write(readBytes);
return Result.ok("下载成功");
}
4、文件删除
@PostMapping("/deleteFile")
public Result deleteFile(@RequestParam("fileName") String fileName) throws JSONException {
File file = new File(fileBean.getDir() + File.separator + fileName);
// 判断文件不为null或文件目录存在
if (file == null || !file.exists()) {
return Result.fail("文件不存在!");
}
try {
//判断是否是文件类型
if (file.isFile()) file.delete();
else {
// 文件夹, 需要先删除文件夹下面所有的文件, 然后删除
for (File temp : file.listFiles()) {
temp.delete();
}
file.delete();
}
} catch (Exception e) {
log.error("发生错误: {}", e);
return Result.fail(e.getMessage());
}
return Result.ok("删除成功");
}
五、总结
实际项目中,将文件上传到本地服务器的可能不大,一般都是上传到远端,比如阿里云文件存储等。其次,这种文件上传只能上传小文件,如果上传大文件会占用内存,进而导致程序崩溃。