简介:
【文件上传和下载】文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。
该文章主要完成简单的文件上传到本地和下载的功能。
文件上传和下载:
1、在application.yml配置文件中设置文件存储路径,如下,也可以指定目录tempFilePath: D:/files/;以及在配置文件中设定文件上传大小限制 multipart,如下,如果需要设定具体值,则直接在文件size和请求size后面写上具体的大小,如:max-file-size: 50Mb
#配置文件大小上传限制,此处设定不限制大小
spring:
application:
name: fota-admin
profiles:
active: dev
servlet:
multipart:
maxFileSize: -1
maxRequestSize: -1
#临时文件地址
#此路径没有指定哪个磁盘,项目服务在哪个磁盘里启动,对应的会在该磁盘下创建该目录
tempFilePath: /tmp/
2、Controller层
/**
* 文件上传
*/
@PostMapping("/upload")
public Long upload(@RequestParam MultipartFile file){
return fileService.upload(file);
}
/**
* 文件下载
*/
@GetMapping("/download/{id}")
public void download(@PathVariable Long id, HttpServletRequest req, HttpServletResponse res) {
fileService.download(id, req, res);
}
3、Service层
路径存储在数据库,下载时通过数据库id,获取路径下载
@Value("${tempFilePath}")
private String tempFilePath;
@Override
public Long upload(MultipartFile file) {
if(file == null || file.isEmpty()){
return null;
}
//获取文件名
String fileName = file.getOriginalFilename();
//获取文件的后缀名
String suffixName = fileName.substring(fileName.lastIndexOf("."));
//获取文件大小
int fileSize = (int)file.getSize();
//获取日期
String date = formatDate("yyyy-MM-dd", System.currentTimeMillis());
//文件路径
String path = tempFilePath+date+"/"+fileName;
//文件存储路径:保存到数据库
String filePath = date+"/"+fileName;
java.io.File dest = new java.io.File(path);
// 判断路径是否存在,如果不存在则创建
if(!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
//保存文件
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(path));
outputStream.write(file.getBytes());
outputStream.flush();
outputStream.close();
//保存相关信息到数据库
File files = new File();
files.setName(fileName);
files.setObjectType(suffixName);
files.setFileSize(fileSize);
files.setFilePath(filePath);
files.setCreateUser(BaseContextHandler.getLoginName());
files.setCreateDate(System.currentTimeMillis());
fileRepository.save(files);
return files.getId();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new BadRequestException(e.getMessage());
}
}
@Override
public void download(Long id, HttpServletRequest req, HttpServletResponse res){
if (id != null) {
File entity = fileRepository.findById(id).get();
String path = tempFilePath+entity.getFilePath();
setDownloadContent(entity.getName(), req, res);
// 重要,需要设置此值,否则下载后打开文件会提示文件需要修复
res.setContentLength(entity.getFileSize());
java.io.File file = new java.io.File(path);
if (file.exists()) {
byte[] buffer = new byte[1024];
//输出流
OutputStream os;
try (FileInputStream fis= new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);) {
os = res.getOutputStream();
int i = bis.read(buffer);
while (i != -1){
os.write(buffer,0,i);
i = bis.read(buffer);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new BadRequestException(e.getMessage());
}
}
}
}
/**
* 客户端下载文件上response header的设置。
*
* @param fileName 文件名
* @param request 请求
* @param response 响应
*/
private void setDownloadContent(String fileName, HttpServletRequest request, HttpServletResponse response) {
String agent = request.getHeader("User-Agent");
try {
if (null != agent && agent.toUpperCase().indexOf("MSIE") > 0) {
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
}
} catch (UnsupportedEncodingException e1) {
}
response.setContentType("application/x-msdownload;");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
}
文件上传细节:
- 文件大小限制配置
- 文件覆盖:文件上传,在同一个目录下重名,后上传的文件会覆盖前一个文件,所以建议给文件名设置为唯一。可采用uuid设置文件名。
//在upload接口修改如下
//获取文件名:保存到数据库,该文件原始的名字
String fileName = file.getOriginalFilename();
//获取唯一文件名:存储在磁盘和数据库里的路径用uuid
String name = getUuid();
//文件路径
String path = tempFilePath+date+"/"+name;
//文件存储路径:保存到数据库
String filePath = date+"/"+name;
/**
* 获取uuid
*/
public static String getUuid() {
return UUID.randomUUID().toString();
}