外协人员,批量上传附件

This commit is contained in:
2025-11-19 14:38:32 +08:00
parent 7b9aadc020
commit 5ac9d5ed0a
7 changed files with 1917 additions and 5 deletions

View File

@@ -139,6 +139,12 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.26.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,654 @@
package com.jeelowcode.tool.framework.common.util.io;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* 文件处理
* 创建人QQ2751682847
* 创建时间2014年12月23日
*/
@Slf4j
public class FileUtil {
/**
* 获取文件大小 返回 KB 保留3位小数 没有文件时返回0
* @param filepath 文件完整路径,包括文件名
* @return
*/
public static Double getFilesize(String filepath) {
File backupath = new File(filepath);
return Double.valueOf(backupath.length()) / 1000.000;
}
/**
* 创建目录
* @param destDirName 目标目录名
* @return
*/
public static Boolean createDir(String destDirName) {
File dir = new File(destDirName);
if (!dir.getParentFile().exists()) { //判断有没有父路径,就是判断文件整个路径是否存在
return dir.getParentFile().mkdirs(); //不存在就全部创建
}
return false;
}
/**
* 删除文件
* @param filePathAndName String 文件路径及名称 如c:/fqf.txt
* @return boolean
*/
public static void delFile(String filePathAndName) {
try {
String filePath = filePathAndName;
filePath = filePath.toString();
File myDelFile = new File(filePath);
myDelFile.delete();
} catch (Exception e) {
System.out.println("删除文件操作出错");
e.printStackTrace();
}
}
/**
* 读取到字节数组0
* @param filePath //路径
* @throws IOException
*/
public static byte[] getContent(String filePath) throws IOException {
File file = new File(filePath);
long fileSize = file.length();
if (fileSize > Integer.MAX_VALUE) {
System.out.println("file too big...");
return null;
}
FileInputStream fi = new FileInputStream(file);
byte[] buffer = new byte[(int) fileSize];
int offset = 0;
int numRead = 0;
while (offset < buffer.length
&& (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
offset += numRead;
}
// 确保所有数据均被读取
if (offset != buffer.length) {
throw new IOException("Could not completely read file " + file.getName());
}
fi.close();
return buffer;
}
public static byte[] toByteArray(File file) throws IOException {
if (file == null || !file.exists()) {
throw new FileNotFoundException("文件不存在");
}
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int len;
while ((len = fis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
return bos.toByteArray();
}
}
/**
* 读取到字节数组1
* @param filePath
* @return
* @throws IOException
*/
public static byte[] toByteArray(String filePath) throws IOException {
File f = new File(filePath);
if (!f.exists()) {
throw new FileNotFoundException(filePath);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
BufferedInputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(f));
int buf_size = 1024;
byte[] buffer = new byte[buf_size];
int len = 0;
while (-1 != (len = in.read(buffer, 0, buf_size))) {
bos.write(buffer, 0, len);
}
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
bos.close();
}
}
/**
* 读取到字节数组2
* @param filePath
* @return
* @throws IOException
*/
public static byte[] toByteArray2(String filePath) throws IOException {
File f = new File(filePath);
if (!f.exists()) {
throw new FileNotFoundException(filePath);
}
FileChannel channel = null;
FileInputStream fs = null;
try {
fs = new FileInputStream(f);
channel = fs.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
while ((channel.read(byteBuffer)) > 0) {
// do nothing
// System.out.println("reading");
}
return byteBuffer.array();
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Mapped File way MappedByteBuffer 可以在处理大文件时,提升性能
* @param filePath
* @return
* @throws IOException
*/
public static byte[] toByteArray3(String filePath) throws IOException {
FileChannel fc = null;
RandomAccessFile rf = null;
try {
rf = new RandomAccessFile(filePath, "r");
fc = rf.getChannel();
MappedByteBuffer byteBuffer = fc.map(MapMode.READ_ONLY, 0,
fc.size()).load();
//System.out.println(byteBuffer.isLoaded());
byte[] result = new byte[(int) fc.size()];
if (byteBuffer.remaining() > 0) {
// System.out.println("remain");
byteBuffer.get(result, 0, byteBuffer.remaining());
}
return result;
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
try {
rf.close();
fc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 判断文件及目录是否存在,若不存在则创建文件及目录
* @param filepath
* @return
* @throws Exception
*/
public static File checkExist(String filepath) throws Exception {
File file = new File(filepath);
if (file.exists()) {//判断文件目录的存在
if (!file.isDirectory()) {//判断文件的存在性
file.createNewFile();//创建文件
System.out.println("文件不存在,创建文件成功!");
}
} else {
System.out.println("文件夹不存在!");
File file2 = new File(file.getParent());
file2.mkdirs();
System.out.println("创建文件夹成功!");
if (!file.isDirectory()) {
file.createNewFile();//创建文件
System.out.println("文件不存在,创建文件成功!");
}
}
return file;
}
/**
* 根据路径,日期关键字下载文件,若有多个,合并成压缩文件下载
* @param request request
* @param response response
* @param fileFolder fileFolder
* @param fileNameStart fileNameStart
*/
public static void downfile(HttpServletRequest request, HttpServletResponse response,
String fileFolder, String fileNameStart) {
File file = new File(fileFolder);
File[] listfile = file.listFiles();
List<Map<String, String>> listfileNew = new ArrayList<>();
//2种情况:日期传参4个文件夹里的多个文件不传参最新的4个文件
if (StringUtils.isEmpty(fileNameStart)) {
for (File fileeach : listfile) {
if (fileeach.getName().endsWith(".log")) {
Map<String, String> map = new HashMap<>();
map.put("filename", fileeach.getName());
map.put("filepath", fileeach.getPath());
listfileNew.add(map);
}
}
} else {
for (File fileeach : listfile) {
if (fileeach.isDirectory()) {
File[] listfilesecond = fileeach.listFiles();
for (File fileeachsecond : listfilesecond) {
Map<String, String> mapsecond = new HashMap<>();
if (fileeachsecond.getName().endsWith(".log") && fileeachsecond.getName().contains(fileNameStart)) {
mapsecond.put("filename", fileeachsecond.getName());
mapsecond.put("filepath", fileeachsecond.getPath());
listfileNew.add(mapsecond);
}
}
}
}
}
if (listfileNew.size() == 1) {
outfiles(request, response, new File(listfileNew.get(0).get("filepath")));
} else if (listfileNew.size() > 1) {
File zipfile = zipFiles(listfileNew, fileFolder);
outfiles(request, response, zipfile);
zipfile.delete();
}
}
/**
* 压缩多个文件
* @param listfileNew listfileNew
* @param fileFolder fileFolder
* @return File
*/
public static File zipFiles(List<Map<String, String>> listfileNew, String fileFolder) {
File zipFile = new File(fileFolder + ".zip");
// 创建 FileOutputStream 对象
FileOutputStream fileOutputStream = null;
// 创建 ZipOutputStream
ZipOutputStream zipOutputStream = null;
// 创建 FileInputStream 对象
FileInputStream fileInputStream = null;
try {
// 实例化 FileOutputStream 对象
fileOutputStream = new FileOutputStream(zipFile);
// 实例化 ZipOutputStream 对象
zipOutputStream = new ZipOutputStream(fileOutputStream);
// 创建 ZipEntry 对象
ZipEntry zipEntry = null;
// 遍历源文件数组
for (int i = 0; i < listfileNew.size(); i++) {
// 将源文件数组中的当前文件读入 FileInputStream 流中
fileInputStream = new FileInputStream(listfileNew.get(i).get("filepath"));
// 实例化 ZipEntry 对象,源文件数组中的当前文件
zipEntry = new ZipEntry(listfileNew.get(i).get("filename"));
zipOutputStream.putNextEntry(zipEntry);
// 该变量记录每次真正读的字节个数
int len;
// 定义每次读取的字节数组
byte[] buffer = new byte[1024];
while ((len = fileInputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
}
fileInputStream.close();
zipOutputStream.closeEntry();
zipOutputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return zipFile;
}
/**
* 下载文件到浏览器
* @param request request
* @param response response
* @param filepath filepath
*/
private static void outfiles(HttpServletRequest request, HttpServletResponse response, File filepath) {
String contentType = "application/octet-stream";
try {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
long fileLength = filepath.length();
response.setContentType(contentType);
response.setHeader("Content-disposition",
"attachment; filename=" + new String(filepath.getName().getBytes("utf-8")));
response.setHeader("Content-Length", String.valueOf(fileLength));
response.setHeader("filename", URLEncoder.encode(filepath.getName(), "UTF-8"));
response.setHeader("Access-Control-Expose-Headers", "filename");
bis = new BufferedInputStream(new FileInputStream(filepath.getPath()));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bos.close();
bis.close();
} catch (Exception e) {
System.out.println("文件下载失败!");
}
}
public static byte[] object2Bytes(Object value) {
if (value == null) {
return null;
}
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream outputStream;
try {
outputStream = new ObjectOutputStream(arrayOutputStream);
outputStream.writeObject(value);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
arrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return arrayOutputStream.toByteArray();
}
//反序列化方法
public Object byte2Object(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
try {
ObjectInputStream inputStream;
inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
Object obj = inputStream.readObject();
return obj;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static String getType(File file) {
return cn.hutool.core.io.FileUtil.getType(file);
}
/**
* 根据路径获取所有的文件名列表
*/
public static List<String> getFiles(String path) {
List<String> fileList = new ArrayList<>();
try {
File file = new File(path);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File fileIndex : files) {
//如果这个文件是目录,则进行递归搜索
if (fileIndex.isDirectory()) {
getFiles(fileIndex.getPath());
} else {
//如果文件是普通文件,则将文件句柄放入集合中
fileList.add(fileIndex.getName());
}
}
} else if ("zip".equals(FileUtil.getType(file)) || "rar".equals(FileUtil.getType(file))) {
ZipInputStream in = new ZipInputStream(new FileInputStream(file));
ZipEntry entry;
//遍历压缩文件内部 文件数量
while ((entry = in.getNextEntry()) != null) {
if (!entry.isDirectory()) {
fileList.add(entry.getName());
} else {
File[] files = file.listFiles();
for (File fileIndex : files) {
//如果这个文件是目录,则进行递归搜索
if (fileIndex.isDirectory()) {
getFiles(fileIndex.getPath());
} else {
//如果文件是普通文件,则将文件句柄放入集合中
fileList.add(fileIndex.getName());
}
}
}
}
} else {
fileList.add(file.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
return fileList;
}
/**
* 根据多个文件路径打包下载文件
* @param request request
* @param response response
* @param filePaths filePaths
*/
public static void downfiles(HttpServletRequest request, HttpServletResponse response,
List<String> filePaths, String zipName) {
List<File> listfile = new ArrayList<>();
for (String filePath : filePaths) {
listfile.add(new File(filePath));
}
if (listfile.size() == 1) {
outfiles(request, response, listfile.get(0));
} else if (listfile.size() > 1) {
List<Map<String, String>> listfileNew = new ArrayList<>();
for (File fileeach : listfile) {
Map<String, String> map = new HashMap<>();
map.put("filename", fileeach.getName());
map.put("filepath", fileeach.getPath());
listfileNew.add(map);
}
File zipfile = zipFiles(listfileNew, zipName);
outfiles(request, response, zipfile);
zipfile.delete();
}
}
/**
* 功能:压缩多个文件文件夹成一个zip文件
* @param srcfile源文件列表
* @param zipfile压缩后的文件
*
*/
public static String zipFileFolders(List<File> srcfile, File zipfile) {
byte[] buf = new byte[1024];
ZipOutputStream out = null;
try {
//ZipOutputStream类完成文件或文件夹的压缩
out = new ZipOutputStream(new FileOutputStream(zipfile));
for (int i = 0; i < srcfile.size(); i++) {
FileInputStream in = new FileInputStream(srcfile.get(i));
String filePath = "";
if (filePath == null) {
filePath = "";
} else {
filePath += "/";
}
out.putNextEntry(new ZipEntry(filePath + srcfile.get(i).getName()));
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
}
out.close();
return zipfile.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 将文件解压缩,并且展平到指定目录
* @param srcZipFile 待解压的文件
* @param destDir 解压目录
* @return
*/
public static List<File> unzipFile(File srcZipFile, File destDir) throws IOException {
if (!destDir.exists()) {
destDir.mkdirs();
}
// 创建 ZipFile 对象
List<File> list = new ArrayList<>();
try (ZipFile zipFile = new ZipFile(srcZipFile)) {
// 循环遍历 ZIP 文件中的条目
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
// 构建解压后的文件路径
String entryName = entry.getName();
File entryFile = new File(destDir, entryName);
if (entry.isDirectory()) {
// 如果是目录,则忽略。
// 万一不同目录里面的文件,存在重名呢,是覆盖还是不覆盖?
// 是保留最先发现的文件,还是保留最后发现的文件
} else {
// 如果是文件,则创建对应的文件,并写入内容
try (InputStream inputStream = zipFile.getInputStream(entry);
FileOutputStream outputStream = new FileOutputStream(entryFile)) {
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
list.add(entryFile);
} catch (Exception e) {
log.error("解压文件失败!" , e);
}
}
}
}
return list;
}
/**
* 从URL下载文件到临时目录
* @param fileUrl 文件URL
* @return 下载后的临时文件
* @throws IOException IO异常
*/
public static File downloadFileFromUrl(String fileUrl) throws IOException {
URL url = new URL(fileUrl);
String fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
if (fileName.isEmpty()) {
fileName = "download_" + System.currentTimeMillis() + ".zip";
}
File tempFile = File.createTempFile("download_", "_" + fileName);
tempFile.deleteOnExit();
try (InputStream in = url.openStream();
FileOutputStream out = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
}
log.info("文件下载成功: {}", tempFile.getAbsolutePath());
return tempFile;
}
/**
* 递归删除目录
* @param directory 要删除的目录
*/
public static void deleteDirectory(File directory) {
if (directory.exists()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
file.delete();
}
}
}
directory.delete();
}
}
}