外协人员,批量上传附件

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

File diff suppressed because one or more lines are too long

View File

@@ -5,25 +5,37 @@ import cn.hutool.json.JSONUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.jeelowcode.core.framework.controller.BaseController;
import com.jeelowcode.core.framework.service.IFormService;
import com.jeelowcode.core.framework.service.IFrameSqlService;
import com.jeelowcode.framework.exception.JeeLowCodeException;
import com.jeelowcode.framework.global.JeeLowCodeBaseConstant;
import com.jeelowcode.framework.plus.SqlHelper;
import com.jeelowcode.framework.plus.build.buildmodel.wrapper.SqlInfoQueryWrapper;
import com.jeelowcode.framework.tenant.annotation.JeeLowCodeTenantIgnore;
import com.jeelowcode.framework.utils.model.ResultDataModel;
import com.jeelowcode.framework.utils.tool.CollectionUtil;
import com.jeelowcode.service.infra.service.IFileService;
import com.jeelowcode.tool.framework.common.pojo.CommonResult;
import com.jeelowcode.tool.framework.common.util.io.FileUtil;
import com.jeelowcode.tool.framework.security.core.LoginUser;
import com.jeelowcode.tool.framework.security.core.util.SecurityFrameworkUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;
import static com.jeelowcode.tool.framework.common.pojo.CommonResult.success;
@Slf4j
@JeeLowCodeTenantIgnore
@Tag(name = "低代码框架 - 自定义外协人员接口")
@RestController
@@ -34,6 +46,12 @@ public class OutSidePersonController extends BaseController {
@Autowired
private IFormService dbFormService;
@Autowired
private IFileService fileService;
@Autowired
private IFrameSqlService sqlService;
@GetMapping({"/importOutside"})
@ApiOperationSupport(order = 5)
@Operation(summary = "引入外协人员")
@@ -71,4 +89,351 @@ public class OutSidePersonController extends BaseController {
super.addJsonData( Long.valueOf(tableId), licenses);
return success("引入成功");
}
public Map<String, Object> getOutSideByCardNo(String cardNo) {
SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper();
wrapper.setTableName("lc_outside_person");
wrapper.setWhere(where -> {
where.eq("cardNo", cardNo);
});
return sqlService.getDataOneByPlus(wrapper);
}
/**
* 根据压缩文件地址下载、解压文件,并根据文件名(身份证号)更新数据库
*
* 功能说明:
* 1. 根据文件地址支持URL或本地路径下载/读取压缩文件
* 2. 解压缩文件支持zip、rar、7z格式得到文件列表
* 3. 遍历文件列表,每个文件的文件名作为身份证号
* 4. 根据身份证号查询lc_risk_hazard_manage表的cardID字段
* 5. 如果匹配到数据,将文件上传到服务器指定目录
* 6. 更新lc_risk_hazard_manage表的actual_corrective_Attachment字段为文件地址
*
* 使用示例:
* <pre>
* // 方式1使用MyBatis Mapper
* &#64;Autowired
* private RiskHazardManageMapper mapper;
*
* String fileUrl = "http://example.com/files.zip";
* String uploadPath = "/data/uploads";
* int count = FileUtil.processCompressedFileByCardId(fileUrl, uploadPath, mapper);
*
* // 方式2使用JPA Repository需要实现接口
* RiskHazardManageMapper mapper = new RiskHazardManageMapper() {
* &#64;Autowired
* private RiskHazardManageRepository repository;
*
* public RiskHazardManage findByCardId(String cardId) {
* return repository.findByCardId(cardId);
* }
*
* public void updateActualCorrectiveAttachment(String cardId, String fileUrl) {
* RiskHazardManage entity = repository.findByCardId(cardId);
* if (entity != null) {
* entity.setActualCorrectiveAttachment(fileUrl);
* repository.save(entity);
* }
* }
* };
* </pre>
*
* @param fileUrl 压缩文件的地址可以是URL如"http://example.com/file.zip"或本地路径如"/path/to/file.zip"
* @return 处理结果:成功处理的文件数量
* @throws IOException IO异常
*/
public int processCompressedFileByCardId( @RequestBody JSONObject jsonObject) throws IOException {
String fileUrl=jsonObject.get("commitmentAttchment").toString();
if(fileUrl.isEmpty()){
return 0;
}
int successCount = 0;
File tempZipFile = null;
File tempDir = null;
String tableName = "lc_outside_person";
Long detailFormId = dbFormService.getDbFormIdByTableName(tableName);
try {
// 1. 下载文件如果是URL或直接使用本地文件
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
// 从URL下载文件
tempZipFile = FileUtil.downloadFileFromUrl(fileUrl);
} else {
// 本地文件路径
tempZipFile = new File(fileUrl);
if (!tempZipFile.exists()) {
throw new FileNotFoundException("文件不存在: " + fileUrl);
}
}
// 2. 创建临时解压目录
String tempDirPath = System.getProperty("java.io.tmpdir") + File.separator +
"unzip_" + System.currentTimeMillis();
tempDir = new File(tempDirPath);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
// 3. 解压缩文件
List<File> fileList = FileUtil.unzipFile(tempZipFile, tempDir);
log.info("解压文件成功,共 {} 个文件", fileList.size());
List<JSONObject> editDataList = new ArrayList<>();
// 4. 遍历文件列表,处理每个文件
for (File file : fileList) {
try {
// 4.1 获取文件名(身份证号),去掉扩展名
String fileName = file.getName();
String cardId = fileName;
// 如果文件名包含扩展名,去掉扩展名
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex > 0) {
cardId = fileName.substring(0, lastDotIndex);
}
// 4.2 根据身份证号查询数据库
Map<String, Object> entity = getOutSideByCardNo(cardId);
if (entity.isEmpty()) {
log.warn("未找到身份证号对应的记录: {}", cardId);
continue;
}
// 4.3 上传文件到服务器
String uploadPath = uploadFile(file);
entity.put("commitmentAttchment", uploadPath);
editDataList.add(JSONUtil.parseObj(entity));
log.info("处理成功 - 身份证号: {}, 文件: {}", cardId, uploadPath);
successCount++;
} catch (Exception e) {
log.error("处理文件失败: {}", file.getName(), e);
}
}
// 更新数据
super.editJsonData(detailFormId, editDataList);
} finally {
// 清理临时文件
if (tempZipFile != null && tempZipFile.exists() &&
(fileUrl.startsWith("http://") || fileUrl.startsWith("https://"))) {
tempZipFile.delete();
}
if (tempDir != null && tempDir.exists()) {
FileUtil.deleteDirectory(tempDir);
}
}
return successCount;
}
public String uploadFile(File file) throws Exception {
String fileName = file.getName();
//微信图片_20230905094700.png
Long tenantId = -1L;
Long userId = -1L;
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser != null) {
tenantId = loginUser.getTenantId();
userId = loginUser.getId();
}
//每个文件放一个文件夹,防止乱码后找不到正确文件
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HHmmssSSS");
String timeString = now.format(formatter);
String publicPath = "upload/" + tenantId + "/" + userId + "/" + timeString + "/";
String path = publicPath + fileName;
fileName = fileService.getUniqueFileName(fileName, path);
// 解决信创环境下文件名中文乱码导致附件错乱的问题
//path = publicPath + IdUtil.simpleUUID() + (StrUtil.isEmpty(FileUtil.extName(fileName)) ? "" : ("." + FileUtil.extName(fileName)));
String fileUrl = fileService.createFile(fileName, path, FileUtil.toByteArray(file));
return fileUrl;
}
/**
* 根据压缩文件地址下载、解压文件,并根据文件名(身份证号)更新数据库
*
* 功能说明:
* 1. 根据文件地址支持URL或本地路径下载/读取压缩文件
* 2. 解压缩文件支持zip、rar、7z格式得到文件列表
* 3. 遍历文件列表,每个文件的文件名作为身份证号
* 4. 根据身份证号查询lc_risk_hazard_manage表的cardID字段
* 5. 如果匹配到数据,将文件上传到服务器指定目录
* 6. 更新lc_risk_hazard_manage表的actual_corrective_Attachment字段为文件地址
*
* 使用示例:
* <pre>
* // 方式1使用MyBatis Mapper
* &#64;Autowired
* private RiskHazardManageMapper mapper;
*
* String fileUrl = "http://example.com/files.zip";
* String uploadPath = "/data/uploads";
* int count = FileUtil.processCompressedFileByCardId(fileUrl, uploadPath, mapper);
*
* // 方式2使用JPA Repository需要实现接口
* RiskHazardManageMapper mapper = new RiskHazardManageMapper() {
* &#64;Autowired
* private RiskHazardManageRepository repository;
*
* public RiskHazardManage findByCardId(String cardId) {
* return repository.findByCardId(cardId);
* }
*
* public void updateActualCorrectiveAttachment(String cardId, String fileUrl) {
* RiskHazardManage entity = repository.findByCardId(cardId);
* if (entity != null) {
* entity.setActualCorrectiveAttachment(fileUrl);
* repository.save(entity);
* }
* }
* };
* </pre>
*
* @param fileUrl 压缩文件的地址可以是URL如"http://example.com/file.zip"或本地路径如"/path/to/file.zip"
* @return 处理结果:成功处理的文件数量
* @throws IOException IO异常
*/
@PutMapping({"/batchAttachments"})
@ApiOperationSupport(order = 5)
@Operation(summary = "批量上传附件")
public int batchAttachments(@RequestBody JSONObject jsonObject) throws IOException {
String commitmentFileUrl = jsonObject.get("commitmentAttchment") != null ?
jsonObject.get("commitmentAttchment").toString() : "";
String secretFileUrl = jsonObject.get("secretAttchment") != null ?
jsonObject.get("secretAttchment").toString() : "";
if (commitmentFileUrl.isEmpty() && secretFileUrl.isEmpty()) {
return 0;
}
int successCount = 0;
String tableName = "lc_outside_person";
Long detailFormId = dbFormService.getDbFormIdByTableName(tableName);
// 用于存储所有需要更新的数据key为身份证号value为需要更新的字段
Map<String, JSONObject> updateDataMap = new HashMap<>();
// 处理 commitmentAttchment 压缩包
if (!commitmentFileUrl.isEmpty()) {
processCompressedFile(commitmentFileUrl, "commitmentAttchment", updateDataMap);
}
// 处理 secretAttchment 压缩包
if (!secretFileUrl.isEmpty()) {
processCompressedFile(secretFileUrl, "secretAttchment", updateDataMap);
}
// 将Map转换为List用于批量更新
List<JSONObject> editDataList = new ArrayList<>(updateDataMap.values());
if (!editDataList.isEmpty()) {
// 更新数据
super.editJsonData(detailFormId, editDataList);
successCount = editDataList.size();
}
return successCount;
}
/**
* 处理压缩文件的通用方法
* @param fileUrl 压缩文件地址
* @param fieldName 要更新的字段名commitmentAttchment 或 secretAttchment
* @param updateDataMap 用于存储更新数据的Mapkey为身份证号
*/
private void processCompressedFile(String fileUrl, String fieldName,
Map<String, JSONObject> updateDataMap) {
File tempZipFile = null;
File tempDir = null;
try {
// 1. 下载文件如果是URL或直接使用本地文件
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
// 从URL下载文件
tempZipFile = FileUtil.downloadFileFromUrl(fileUrl);
} else {
// 本地文件路径
tempZipFile = new File(fileUrl);
if (!tempZipFile.exists()) {
log.warn("文件不存在: {}", fileUrl);
return;
}
}
// 2. 创建临时解压目录
String tempDirPath = System.getProperty("java.io.tmpdir") + File.separator +
"unzip_" + System.currentTimeMillis() + "_" + fieldName;
tempDir = new File(tempDirPath);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
// 3. 解压缩文件
List<File> fileList = FileUtil.unzipFile(tempZipFile, tempDir);
log.info("解压文件成功 [{}],共 {} 个文件", fieldName, fileList.size());
// 4. 遍历文件列表,处理每个文件
for (File file : fileList) {
try {
// 4.1 获取文件名(身份证号),去掉扩展名
String fileName = file.getName();
String cardId = fileName;
// 如果文件名包含扩展名,去掉扩展名
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex > 0) {
cardId = fileName.substring(0, lastDotIndex);
}
// 4.2 根据身份证号查询数据库
Map<String, Object> entity = getOutSideByCardNo(cardId);
if (entity.isEmpty()) {
log.warn("未找到身份证号对应的记录: {}", cardId);
continue;
}
// 4.3 上传文件到服务器
String uploadPath = uploadFile(file);
// 4.4 更新或添加到更新数据Map中
String cardIdKey = cardId;
JSONObject updateData = updateDataMap.get(cardIdKey);
if (updateData == null) {
// 如果Map中还没有这个身份证号的记录创建新记录
updateData = JSONUtil.parseObj(entity);
updateDataMap.put(cardIdKey, updateData);
}
// 更新对应的字段
updateData.put(fieldName, uploadPath);
log.info("处理成功 [{}] - 身份证号: {}, 文件: {}", fieldName, cardId, uploadPath);
} catch (Exception e) {
log.error("处理文件失败 [{}]: {}", fieldName, file.getName(), e);
}
}
} catch (Exception e) {
log.error("处理压缩文件失败 [{}]: {}", fieldName, fileUrl, e);
} finally {
// 清理临时文件
if (tempZipFile != null && tempZipFile.exists() &&
(fileUrl.startsWith("http://") || fileUrl.startsWith("https://"))) {
tempZipFile.delete();
}
if (tempDir != null && tempDir.exists()) {
FileUtil.deleteDirectory(tempDir);
}
}
}
}

View File

@@ -1,6 +1,7 @@
package com.jeelowcode.module.biz.controller;
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -11,21 +12,41 @@ import com.jeelowcode.framework.global.JeeLowCodeBaseConstant;
import com.jeelowcode.framework.tenant.annotation.JeeLowCodeTenantIgnore;
import com.jeelowcode.framework.utils.model.ResultDataModel;
import com.jeelowcode.framework.utils.tool.CollectionUtil;
import com.jeelowcode.module.biz.service.IRiskService;
import com.jeelowcode.service.infra.controller.vo.file.FileUploadReqVO;
import com.jeelowcode.service.infra.service.IFileService;
import com.jeelowcode.tool.framework.common.pojo.CommonResult;
import com.jeelowcode.tool.framework.common.util.io.FileUtil;
import com.jeelowcode.tool.framework.security.core.LoginUser;
import com.jeelowcode.tool.framework.security.core.util.SecurityFrameworkUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import static com.jeelowcode.tool.framework.common.pojo.CommonResult.success;
/**
* @author LIFY
* @create 2025-09-126
* @dedescription:
*/
@JeeLowCodeTenantIgnore
@Tag(name = "低代码框架 - 个性化接口")
@RestController
@@ -36,6 +57,11 @@ public class RiskHazardController extends BaseController {
@Autowired
private IFormService formService;
@Autowired
private IRiskService riskService;
@GetMapping({"/syncData2RiskHazard"})
@ApiOperationSupport(order = 1)
@Operation(summary = "同步数据")
@@ -133,4 +159,6 @@ public class RiskHazardController extends BaseController {
super.editJsonData(dbFormId, syncList);
}
}
}

View File

@@ -22,4 +22,5 @@ public interface IRiskService {
* 根据ID获取当前数据
*/
Map<String, Object> getRiskById(long id);
}

View File

@@ -127,5 +127,4 @@ public class RiskServiceImpl implements IRiskService {
});
return sqlService.getDataOneByPlus(wrapper);
}
}

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();
}
}
}