ps:工作之余仅留备份用,未全面完善,请按需取用
一、主要关注两点:1.找到文件并压缩;2.通过文件输出流响应前端
@RestController
@RequestMapping("/file")
public class FileController extends BaseController {
@Autowired
private StorageServerService storageServerService;
@Autowired
private FileInfoService fileInfoService;
@Autowired
private CompactFileService compactFileService;
@Autowired
private Environment env;
/**
* 上传文件
*/
@RequestMapping("/upload")
public SysMsgItems<Object> upload(MultipartFile file) throws IOException {
StorageServer server = storageServerService.getStorageServer();
String fileUrl = DateUtils.formatDate(new Date(), "yyyyMMdd");
if (!Files.exists(Paths.get(server.getStorageDir() + File.separator + fileUrl))) {
Files.createDirectories(Paths.get(server.getStorageDir() + File.separator + fileUrl));
}
String fileName = file.getOriginalFilename();
String _fileName = UUID.randomUUID().toString();
if (fileName.lastIndexOf(".") >= 0) {
_fileName = _fileName + fileName.substring(fileName.lastIndexOf("."));
}
fileUrl = fileUrl + File.separator + _fileName;
File f = new File(server.getStorageDir() + File.separator + fileUrl);
OutputStream os = new FileOutputStream(f);
long fileSize = IOUtils.copyLarge(file.getInputStream(), os);
IOUtils.closeQuietly(os);
InputStream in = new FileInputStream(f);
String md5 = DigestUtils.md5DigestAsHex(in);
in.close();
String fId = fileInfoService.create(fileName, fileSize, md5, server.getId(), fileUrl);
SysMsgItems<Object> result = new SysMsgItems<Object>();
result.setItems(new ParamUtils.ParamBuilder()
.set("success", true)
.set("fileUrl", fileUrl)
.set("fileSize", fileSize)
.set("fId", fId)
.build());
return result;
}
/**
* 下载文件
*/
@RequestMapping("/download")
public void download1(String fileUrl, String size, String fileName, HttpServletResponse response) {
InputStream inStream = null;
OutputStream os = null;
try {
String fileStorageUrl = fileInfoService.getFileStoragePathByFileUrl(fileUrl);
if (!ObjectUtils.isEmpty(fileStorageUrl)) {
inStream = new FileInputStream(fileStorageUrl);
String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
response.addHeader("Content-Length", "" + size);
if (fileName.toLowerCase().endsWith("pdf")) {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
} else {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
}
os = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[1024];
int count = 0;
while ((count = inStream.read(buffer)) >= 0) {
os.write(buffer, 0, count);
os.flush();
}
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
} catch (Exception e) {
logger.error(ExceptionCollect.collectExceptionStackMsg(e));
} finally {
try {
os.flush();
inStream.close();
} catch (Exception e2) {
logger.error(ExceptionCollect.collectExceptionStackMsg(e2));
}
}
}
/**
* 批量文件压缩下载
*
* @author wangxy2
* @since 2022/4/22
*/
@RequestMapping("/downloadByCompact")
public void downloadByCompact(@RequestBody Map<Object, Object> params, HttpServletResponse response) {
OutputStream os = null;
ZipOutputStream out = null;
try {
String businessNum = ParamUtils.getString(params, "businessNum", String.format("%s_batch", UserPrincipalUtils.getUserPrincipal().getUserName())),
encodedFileName = java.net.URLEncoder.encode(businessNum + ".zip", "utf-8");
response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
response.setContentType("application/octet-stream");
// 创建zip输出流
out = new ZipOutputStream(response.getOutputStream());
// 创建缓冲输出流
os = new BufferedOutputStream(out);
List<Map<Object, Object>> fileInfoList = (List<Map<Object, Object>>) params.get("fileInfoList");
for (Map<Object, Object> fileInfoMap : fileInfoList) {
String fileUrl = ParamUtils.getString(fileInfoMap, "fileUrl", ""),
fileName = ParamUtils.getString(fileInfoMap, "fileName", "");
// 此处是获取文件的物理绝对地址
String fileStorageUrl = fileInfoService.getFileStoragePathByFileUrl(fileUrl);
// 压缩单个文件
File srcfile = new File(fileStorageUrl);
compactFileService.compress(srcfile, out, "", fileName);
}
os.flush();
logger.info("==批量文件压缩完毕==");
} catch (Exception e) {
logger.error("==批量文件压缩下载失败,原因:{}==", e.getMessage());
} finally {
try {
if (os != null) {
os.flush();
}
if (out != null) {
out.close();
}
} catch (Exception e2) {
logger.error("==批量文件压缩下载-关闭流失败,原因:{}==", e2.getMessage());
}
}
}
}
二、此处更关注的是:文件的物理绝对地址并不是源文件名称,需要在压缩的时候,指定压缩条目(文件)名称
package cn.qh.filecenter.files.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 压缩文件
*
* @author wangxy2
* @since 2022/4/22
*/
@Service("compactFileService")
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class CompactFileService {
private static Logger logger = LoggerFactory.getLogger(CompactFileService.class);
/**
* 压缩文件夹里的文件
* 起初不知道是文件还是文件夹--- 统一调用该方法
*/
public void compress(File file, ZipOutputStream out, String basedir) {
/* 判断是目录还是文件 */
if (file.isDirectory()) {
this.zipDirectory(file, out, basedir);
} else {
this.zipFile(file, out, basedir);
}
}
/**
* 压缩文件夹
*/
public void zipDirectory(File dir, ZipOutputStream out, String basedir) {
if (!dir.exists()) {
return;
}
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
compress(files[i], out, basedir + dir.getName() + "/");
}
}
/**
* 压缩单个文件
*/
public void zipFile(File srcfile, ZipOutputStream out, String basedir) {
if (!srcfile.exists()) {
return;
}
byte[] buf = new byte[1024];
FileInputStream in = null;
try {
int len;
in = new FileInputStream(srcfile);
out.putNextEntry(new ZipEntry(basedir + srcfile.getName()));
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.closeEntry();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*-------------- 指定fileName --------------------*/
/**
* 压缩文件夹里的文件(使用指定的名称创建新的zip文件)
* 起初不知道是文件还是文件夹--- 统一调用该方法
*/
public void compress(File file, ZipOutputStream out, String basedir, String fileName) {
if (file.isDirectory()) {
/* 当前file是目录,需要循环遍历 */
this.zipDirectory(file, out, basedir);
} else if (ObjectUtils.isEmpty(fileName)) {
// 没有指定文件名称,使用文件物理地址文件名
this.zipFile(file, out, basedir);
} else {
this.zipFile(file, out, basedir, fileName);
}
}
/**
* 压缩单个文件(使用指定的名称创建新的zip文件)
*/
public void zipFile(File srcfile, ZipOutputStream out, String basedir, String fileName) {
if (!srcfile.exists()) {
return;
}
byte[] buf = new byte[1024];
FileInputStream in = null;
try {
int len;
in = new FileInputStream(srcfile);
// ZipEntry: Creates a new zip entry with the specified name.
out.putNextEntry(new ZipEntry(basedir + fileName));
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.closeEntry();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}