一、上传文件(以批次为例)
A服务(服务提供者)
控制层:
@ApiOperation("批量文件上传")
@PostMapping("/uploadFiles")
//响应的是k:文件名 v:文件存储路径
public JsonResult
业务层:
//类常量引用
@Resource
MultipartConfigElement config;
@Override
public Map uploadFiles(MultipartFile[] files) throws IOException {
if (files == null ||files.length == 0) {
return null;
}
Map map = new HashMap<>();
for (MultipartFile file : files) {
if (!file.isEmpty()) {
//获取默认的绝对路径
String localtion = config.getLocation();
//创建自定义路径并返回路径字符串
String fileDir = FileUploadUtils.uploadFile(localtion, file);
map.put(file.getOriginalFilename(), fileDir);
}
}
return map;
}
//可以自己写一个配置类文件或者直接放在启动类(配置的目的还是自己定义绝对路径)
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
String osName = System.getProperty("os.name").toLowerCase();
String path = "";
if( osName.indexOf(WINDOWS) >= 0){
path = "d:/data/temp/";
}else{
path = "/root/data/temp";
}
if(!FileUtil.exist(path)){
FileUtil.mkdir(path);
}
factory.setLocation(path);
factory.setMaxFileSize(DataSize.parse(maxFileSize));
factory.setMaxRequestSize(DataSize.parse(maxRequestSize));
return factory.createMultipartConfig();
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String uploadFile(String baseDir, MultipartFile file) throws IOException {
return upload(baseDir, file);
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 返回上传成功的文件名
* @throws IOException 异常
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException{
String fileName = file.getOriginalFilename();
//校验文件名称长度
checkFileNameLength(fileName);
//获取保存的目录路径
String fileDir = getFileDir(baseDir, fileName);
//写文件
file.transferTo(new File(fileDir,fileName));
return fileDir;
}
/**
* 检查文件名称长度
* @param fileName 文件名称
*/
public static final void checkFileNameLength(String fileName) {
if (fileName.length() > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileException(FileExceptionEnums.FILE_NAME_TOO_LONG);
}
}
/**
* 生成文件路径
* */
private static final String getFileDir(String uploadDir, String fileName) {
String ext = FileUtil.extName(fileName);
String datePath = DateUtils.datePath();
//储存路径
StringBuilder path = new StringBuilder();
path.append(uploadDir).append(datePath).append("/").append(ext).append("/");
//path一定是绝对路径例如d:xxx/xxx或者linux root/xx/xx 否则会提示异常
File fileDir = new File(path.toString());
if (!fileDir.exists()){
fileDir.mkdirs();
}
return path.toString();
}
如果无需跨服务调用,到此上传结束!!!!
跨服务调用(消费服务B调用A服务接口):
Feign:
@PostMapping(value = "/filesystem/uploadFiles",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
JsonResult
B服务的实现不多介绍
二、下载文件
推荐两种方式:
方式一:java通用下载
服务提供层A:
@ApiOperation("下载单个文件")
@GetMapping("/downloadFile")
public void downloadFile(String path, String fileName, HttpServletResponse response){
fileService.downloadFile(path, fileName, response);
}
@Override
public void downloadFile(String path,String fileName, HttpServletResponse response) {
//获取文件
File file= getFile(path, fileName);
if(file == null) {
throw new FileException(FileExceptionEnums.FILE_NOT_FOUND);
}
//1 设置response 响应头
response.reset();
response.setCharacterEncoding("UTF-8");
//2 设置响应文本类型,以xlsx格式为例(可以参考:https://blog.csdn.net/josavion/article/details/115260427)
response.setContentType("application/octet-stream");
//fileName我的文件名带后缀的,如果无后缀,这里要补齐"attachment;filename="+ fileName + ".xlsx"
response.setHeader("Content-Disposition",
"attachment;filename="+ fileName);
try {
//读取文件--输入流
InputStream input = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(input);
//写出文件--输出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
int length = 0;
byte[] temp = new byte[1024 * 10];
while ((length = bufferedInputStream.read(temp)) != -1) {
bufferedOutputStream.write(temp, 0, length);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
bufferedInputStream.close();
input.close();
} catch (IOException e) {
log.error("文件:{}下载失败,",fileName,e);
throw new FileException(FileExceptionEnums.DOWN_LOAD_ERROR);
}
}
private File getFile(String path, String fileName) {
File file = new File(path + fileName);
if (!(file.exists() && file.canRead())) {
return null;
}
return file;
}
Feign:
@GetMapping("/filesystem/downloadFile")
//返回的是Response
Response downloadFile(@RequestParam("path") String path, @RequestParam("fileName") String fileName);
B调用A:
@Override
public void getFile(String path, String fileName, HttpServletResponse response) throws IOException {
InputStream inputStream = null;
Response serviceResponse = fileClient.downloadFile(path, fileName);
//获取body
Response.Body body = serviceResponse.body();
//输入流
inputStream = body.asInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
//输出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
int length = 0;
byte[] temp = new byte[1024 * 10];
while ((length = bufferedInputStream.read(temp)) != -1) {
bufferedOutputStream.write(temp, 0, length);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();
bufferedInputStream.close();
inputStream.close();
}
方式二:基于ResponseEntity实现(建议)
A服务:
@ApiOperation("下载单个文件")
@GetMapping("/downloadFileBytes")
public ResponseEntity downloadFileBytes(String path, String fileName) throws IOException {
return fileService.downloadFileBytes(path, fileName);
}
//业务层
@Override
public ResponseEntity downloadFileBytes(String path, String fileName) throws IOException {
File file= getFile(path, fileName);
if(file == null) {
throw new FileException(FileExceptionEnums.FILE_NOT_FOUND);
}
HttpHeaders headers = new HttpHeaders();
String filename = new String(fileName.getBytes("utf-8"),"iso-8859-1");
headers.setContentDispositionFormData("attachment", filename);
//感兴趣的可以去看一下MediaType
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
}
private File getFile(String path, String fileName) {
File file = new File(path + fileName);
if (!(file.exists() && file.canRead())) {
return null;
}
return file;
}
Feign:
@GetMapping("/filesystem/downloadFileBytes")
ResponseEntity downloadFileBytes(@RequestParam("path") String path, @RequestParam("fileName") String fileName) throws IOException;
B调用A:
@Override
public ResponseEntity getFileBytes(String path, String fileName) throws IOException {
String resourceName = report.getFileName();
ResponseEntity data = fileClient.downloadFileBytes(path,fileName);
return data;
}