SpringBoot后台如何实现文件上传下载?
最近做的一个项目涉及到文件上传与下载。前端上传采用百度webUploader插件。有关该插件的使用方法还在研究中,日后整理再记录。本文主要介绍SpringBoot后台对文件上传与下载的处理。
MultipartConfig配置
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;
import javax.servlet.MultipartConfigElement;
@Configuration
public class multipartConfig {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
// 设置文件大小限制 ,超出此大小页面会抛出异常信息
factory.setMaxRequestSize(DataSize.of(500, DataUnit.MEGABYTES));
// 设置总上传数据总大小
factory.setMaxFileSize(DataSize.of(10, DataUnit.GIGABYTES));
return factory.createMultipartConfig();
}
}
单文件上传
// 单文件上传
@RequestMapping(value = "/upload")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file) {
try {
if (file.isEmpty()) {
return "文件为空";
}
// 获取文件名
String fileName = file.getOriginalFilename();
logger.info("上传的文件名为:" + fileName);
// 获取文件的后缀名
String suffixName = fileName.substring(fileName.lastIndexOf("."));
logger.info("文件的后缀名为:" + suffixName);
// 设置文件存储路径
String filePath = "D://aim//";
String path = filePath + fileName + suffixName;
File dest = new File(path);
// 检测是否存在目录
if (!dest.getParentFile().exists()) {
// 新建文件夹
dest.getParentFile().mkdirs();
}
// 文件写入
file.transferTo(dest);
return "上传成功";
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "上传失败";
}
如果想要修改文件路径及文件名,修改filePath以及fileName即可。
多文件上传
//多文件上传
@RequestMapping(value = "/uploadMore", method = RequestMethod.POST)
public String handleFileUpload(HttpServletRequest request) {
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
MultipartFile file = null;
BufferedOutputStream stream = null;
for (int i = 0; i < files.size(); ++i) {
file = files.get(i);
String filePath = "D://aim//";
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
//设置文件路径及名字
stream = new BufferedOutputStream(new FileOutputStream(
new File(filePath + file.getOriginalFilename())));
// 写入
stream.write(bytes);
stream.close();
} catch (Exception e) {
stream = null;
return "第 " + i + " 个文件上传失败 " + e.getMessage();
}
} else {
return "第 " + i + " 个文件上传失败因为文件为空";
}
}
return "上传成功";
}
.也可以这样来取得上传的file流:
// 文件上传
@RequestMapping("/fileUpload")
public Map fileUpload(@RequestParam("file") MultipartFile file, HttpServletRequest req) {
Map result = new HashMap();
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");// 设置日期格式
String dateDir = df.format(new Date());// new Date()为获取当前系统时间
String serviceName = UuidUtil.get32UUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
File tempFile = new File(fileDir + dateDir + File.separator + serviceName);
if (!tempFile.getParentFile().exists()) {
tempFile.getParentFile().mkdirs();
}
if (!file.isEmpty()) {
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile));
// "d:/"+file.getOriginalFilename() 指定目录
out.write(file.getBytes());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
result.put("msg", "上传失败," + e.getMessage());
result.put("state", false);
return result;
} catch (IOException e) {
e.printStackTrace();
result.put("msg", "上传失败," + e.getMessage());
result.put("state", false);
return result;
}
result.put("msg", "上传成功");
String fileId = Get8uuid.generateShortUuid();
String fileName = file.getOriginalFilename();
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
String fileUrl = webDir + dateDir + '/' + serviceName;
uploadMapper.saveFileInfo(fileId, serviceName, fileType, fileUrl);
result.put("state", true);
return result;
} else {
result.put("msg", "上传失败,因为文件是空的");
result.put("state", false);
return result;
}
}
文件下载
// 文件下载
@RequestMapping("/download")
public String downloadFile(HttpServletRequest request, HttpServletResponse response, String fileName) {
if (StringUtils.isBlank(fileName)) {
throw new IllegalArgumentException("The fileName cannot be empty");
}
//设置文件路径
String realPath = "D://aim//";
File file = new File(realPath, fileName);
if (file.exists()) {
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
文件列表
@RequestMapping(value = "/fileList", method = RequestMethod.GET)
public List<String> list() {
String path = fileStorePath + "merge";
File fileDir = new File(path);
List<String> dirAllStrArr = com.example.recordlog.tools.FileUtils.DirAll(fileDir);
ArrayList<File> dirAllStrArr2 = com.example.recordlog.tools.FileUtils.refreshFileList(path);
File file = null;
for (int i = 0; i < dirAllStrArr.size(); i++) {
file = new File(dirAllStrArr.get(i));
}
return dirAllStrArr;
}
FileUtils功能工具类
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FileUtils {
private FileUtils() {
}
/**
* @Desc 查询当前路径下的所有文件夹(不包含子文件夹)
* @Param
*/
public static ArrayList<String> Dir(File dirFile) {
ArrayList<String> dirStrArr = new ArrayList<String>();
if (dirFile.exists()) {
// 直接取出利用listFiles()把当前路径下的所有文件夹、文件存放到一个文件数组
File files[] = dirFile.listFiles();
for (File file : files) {
// 如果传递过来的参数dirFile是以文件分隔符,也就是/或者\结尾,则如此构造
if (dirFile.getPath().endsWith(File.separator)) {
dirStrArr.add(dirFile.getPath() + file.getName());
} else {
// 否则,如果没有文件分隔符,则补上一个文件分隔符,再加上文件名,才是路径
dirStrArr.add(dirFile.getPath() + File.separator
+ file.getName());
}
}
}
return dirStrArr;
}
/**
* @Desc 递归遍历路径下所有的文件
* @Param
*/
public static List<String> DirAll(File dirFile) {
List<String> resultFile = new ArrayList<>();
File[] files = dirFile.listFiles();
// 判断目录下是不是空的
if (files == null) {
return resultFile;
}
for (File f : files) {
// 判断是否文件夹
if (f.isDirectory()) {
resultFile.add(f.getPath());
// 调用自身,查找子目录
DirAll(f);
} else {
resultFile.add(f.getPath());
}
}
return resultFile;
}
//递归遍历路径下的所有文件
public static ArrayList<File> refreshFileList(String strPath) {
// 存储文件列表
ArrayList<File> fileList = new ArrayList<>();
// 创建文件
File dir = new File(strPath);
// 获取当前路径下的所有文件
File[] files = dir.listFiles();
// 判断文件数组是否为空
if (null == files) {
return null;
}
// 循环遍历所有文件
for (int i = 0, size = files.length; i < size; i++) {
// 如果是文件夹
if (files[i].isDirectory()) {
// 遍历此路径,执行此方法
ArrayList<File> refreshFileList = refreshFileList(files[i].getAbsolutePath());
if (null != refreshFileList) {
fileList.addAll(refreshFileList);
}
} else {
// 添加到文件列表
fileList.add(files[i]);
}
}
return fileList;
}
public static void main(String[] args) {
File file = new File("D:/新建文件夹/merge");
ArrayList<File> dirStrArr = FileUtils.refreshFileList("D:/新建文件夹/merge");
System.out.println(dirStrArr.toString());
}
}
文件上传(前端页面):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/testUpload" method="POST" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit" />
</form>
<a href="/testDownload" >下载</a>
</body>
</html>
表单提交加上enctype="multipart/form-data"很重要,文件以二进制流的形式传输。