|
|
@@ -3,8 +3,9 @@ package com.lc.ibps.cloud.file.provider;
|
|
|
import java.io.*;
|
|
|
import java.net.URL;
|
|
|
import java.net.URLEncoder;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Scanner;
|
|
|
+import java.nio.charset.Charset;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
@@ -19,8 +20,12 @@ import cn.hutool.json.JSONObject;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
import com.lc.ibps.base.core.util.*;
|
|
|
import com.lc.ibps.base.framework.id.UniqueIdUtil;
|
|
|
+import com.lc.ibps.base.framework.table.ICommonDao;
|
|
|
import com.lc.ibps.cloud.redis.utils.RedisUtil;
|
|
|
import com.lc.ibps.common.file.persistence.entity.AttachmentPo;
|
|
|
+import com.lc.ibps.file.server.model.FolderNodeInfo;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.apache.commons.lang3.RandomStringUtils;
|
|
|
import org.jodconverter.OfficeDocumentConverter;
|
|
|
import org.jodconverter.office.DefaultOfficeManagerBuilder;
|
|
|
import org.jodconverter.office.OfficeException;
|
|
|
@@ -44,6 +49,35 @@ import com.lc.ibps.components.upload.baidu.ueditor.ActionEnter;
|
|
|
import com.lc.ibps.components.upload.util.UploadUtil;
|
|
|
import com.lc.ibps.file.server.api.IDownloadService;
|
|
|
|
|
|
+
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.IOException;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.zip.ZipEntry;
|
|
|
+import java.util.zip.ZipInputStream;
|
|
|
+
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
+
|
|
|
+import com.lc.ibps.api.base.constants.StateEnum;
|
|
|
+import com.lc.ibps.api.base.file.FileInfo;
|
|
|
+import com.lc.ibps.base.core.util.BeanUtils;
|
|
|
+import com.lc.ibps.base.framework.id.UniqueIdUtil;
|
|
|
+import com.lc.ibps.base.framework.table.ICommonDao;
|
|
|
+import com.lc.ibps.base.web.context.ContextUtil;
|
|
|
+import com.lc.ibps.cloud.entity.APIResult;
|
|
|
+import com.lc.ibps.common.file.persistence.entity.AttachmentPo;
|
|
|
+import com.lc.ibps.components.upload.constants.FileParam;
|
|
|
+import com.lc.ibps.file.server.model.ZipImportStat;
|
|
|
+
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import io.swagger.annotations.ApiParam;
|
|
|
+
|
|
|
import io.swagger.annotations.Api;
|
|
|
import io.swagger.annotations.ApiOperation;
|
|
|
import io.swagger.annotations.ApiParam;
|
|
|
@@ -62,10 +96,723 @@ import io.swagger.annotations.ExtensionProperty;
|
|
|
@Api(tags = "文件下载", value = "文件下载")
|
|
|
@Service
|
|
|
public class DownloadProvider extends GenericUploadProvider implements IDownloadService{
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ICommonDao<?> commonDao;
|
|
|
+
|
|
|
+ private static final String FOLDER_TABLE = "ibps_cat_type";
|
|
|
+ private static final String KEY_WEN_JIAN_ID = "wen_jian_id_";
|
|
|
+ private static final String KEY_WEN_JIAN_JIA_ID = "wen_jian_jia_id_";
|
|
|
+ private static final String KEY_WEN_JIAN_MING = "wen_jian_ming";
|
|
|
+ private static final String KEY_WEN_JIAN_HAO = "wen_jian_hao_";
|
|
|
+ private static final String FOLDER_CATEGORY_KEY = "FILE_TYPE";
|
|
|
+
|
|
|
/*上传文件*/
|
|
|
@Autowired
|
|
|
private UploadProvider uploadFile;
|
|
|
|
|
|
+
|
|
|
+ @ApiOperation(value = "zip文件解析", notes = "zip文件解析")
|
|
|
+ @Override
|
|
|
+ public APIResult<Map<String, Object>> unzip(
|
|
|
+ @ApiParam(name = "attachmentId", value = "zip附件id", required = true)
|
|
|
+ @RequestParam(name = "attachmentId", required = true) String attachmentId,
|
|
|
+ @ApiParam(name = "parentFolderId", value = "父文件夹id", required = true)
|
|
|
+ @RequestParam(name = "parentFolderId", required = true) String parentFolderId) {
|
|
|
+
|
|
|
+ APIResult<Map<String, Object>> result = new APIResult<>();
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (StringUtils.isBlank(attachmentId)) {
|
|
|
+ result.setState(StateEnum.ERROR.getCode());
|
|
|
+ result.setMessage("zip附件id不能为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(parentFolderId)) {
|
|
|
+ result.setState(StateEnum.ERROR.getCode());
|
|
|
+ result.setMessage("父文件夹id不能为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.getUploadService();
|
|
|
+ FileInfo fileInfo = uploadService.downloadFile(attachmentId);
|
|
|
+ if (BeanUtils.isEmpty(fileInfo)) {
|
|
|
+ result.setState(StateEnum.ERROR.getCode());
|
|
|
+ result.setMessage("zip文件不存在");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!"zip".equals(fileInfo.getExt())) {
|
|
|
+ logger.error("文件不是ZIP格式: {}", fileInfo.getFileName());
|
|
|
+ result.setState(StateEnum.ERROR.getCode());
|
|
|
+ result.setMessage("文件不是ZIP格式,请上传ZIP文件");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ byte[] zipContent = getZipContent(fileInfo);
|
|
|
+ if (zipContent == null || zipContent.length == 0) {
|
|
|
+ logger.error("ZIP文件内容为空,attachmentId: {}", attachmentId);
|
|
|
+ result.setState(StateEnum.ERROR.getCode());
|
|
|
+ result.setMessage("ZIP文件内容为空");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ ZipImportStat stat = importZipToDatabase(zipContent, parentFolderId);
|
|
|
+
|
|
|
+ map.put("folderCount", stat.getFolderCount());
|
|
|
+ map.put("fileCount", stat.getFileCount());
|
|
|
+ map.put("list", stat.getFileMapList());
|
|
|
+ map.put("attachmentId", attachmentId);
|
|
|
+ map.put("parentFolderId", parentFolderId);
|
|
|
+
|
|
|
+ result.setState(StateEnum.SUCCESS.getCode());
|
|
|
+ result.setMessage("ZIP文件解析成功");
|
|
|
+ result.setData(map);
|
|
|
+ return result;
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("/upload/unzip", e);
|
|
|
+ result.setState(StateEnum.ERROR.getCode());
|
|
|
+ result.setMessage("ZIP文件解析失败: " + e.getMessage());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private byte[] getZipContent(FileInfo fileInfo) throws IOException {
|
|
|
+ byte[] zipContent = fileInfo.getFileBytes();
|
|
|
+ if (zipContent != null && zipContent.length > 0) {
|
|
|
+ return zipContent;
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(fileInfo.getFilePath())) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Path filePath = Paths.get(fileInfo.getFilePath());
|
|
|
+ if (!Files.exists(filePath)) {
|
|
|
+ throw new FileNotFoundException("文件不存在: " + fileInfo.getFilePath());
|
|
|
+ }
|
|
|
+ return Files.readAllBytes(filePath);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private ZipImportStat importZipToDatabase(byte[] zipContent, String parentFolderId) throws IOException {
|
|
|
+ ZipImportStat stat = new ZipImportStat();
|
|
|
+
|
|
|
+ FolderNodeInfo rootFolder = queryFolderNodeById(parentFolderId);
|
|
|
+ if (rootFolder == null) {
|
|
|
+ rootFolder = new FolderNodeInfo();
|
|
|
+ rootFolder.setId(parentFolderId);
|
|
|
+ rootFolder.setPath(parentFolderId);
|
|
|
+ rootFolder.setDepth(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(rootFolder.getPath())) {
|
|
|
+ rootFolder.setPath(parentFolderId);
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, FolderNodeInfo> folderCache = new HashMap<>();
|
|
|
+ folderCache.put("", rootFolder);
|
|
|
+
|
|
|
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(zipContent);
|
|
|
+ ZipInputStream zipInputStream = new ZipInputStream(bais, Charset.forName("GBK"))) {
|
|
|
+
|
|
|
+ ZipEntry entry;
|
|
|
+ while ((entry = zipInputStream.getNextEntry()) != null) {
|
|
|
+ try {
|
|
|
+ String entryName = normalizeZipEntryName(entry.getName());
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(entryName) || isIgnoredZipEntry(entryName)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (entry.isDirectory()) {
|
|
|
+ String folderPathInZip = trimTrailingSlash(entryName);
|
|
|
+ ensureFolderImported(folderPathInZip, rootFolder, folderCache, stat);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String parentPathInZip = getParentPathInZip(entryName);
|
|
|
+ FolderNodeInfo dbFolder = ensureFolderImported(parentPathInZip, rootFolder, folderCache, stat);
|
|
|
+
|
|
|
+ String zipFileName = getFileNameFromZipPath(entryName);
|
|
|
+ if (StringUtils.isNotBlank(zipFileName)) {
|
|
|
+ byte[] fileBytes = readZipEntryBytes(zipInputStream);
|
|
|
+ Map<String, Object> fileMap = insertFile(dbFolder.getId(), zipFileName, fileBytes);
|
|
|
+ stat.addFileMap(fileMap);
|
|
|
+ stat.increaseFileCount();
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ zipInputStream.closeEntry();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ logger.info("ZIP文件解析完成,新增文件夹数: {}, 新增文件数: {}", stat.getFolderCount(), stat.getFileCount());
|
|
|
+ return stat;
|
|
|
+ }
|
|
|
+
|
|
|
+/*
|
|
|
+ private ZipImportStat importZipToDatabase(byte[] zipContent, String parentFolderId) throws IOException {
|
|
|
+ ZipImportStat stat = new ZipImportStat();
|
|
|
+
|
|
|
+ String parentPath = queryFolderPathById(parentFolderId);
|
|
|
+ if (StringUtils.isBlank(parentPath)) {
|
|
|
+ parentPath = "";
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, String> folderIdCache = new HashMap<>();
|
|
|
+ folderIdCache.put("", parentFolderId);
|
|
|
+
|
|
|
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(zipContent);
|
|
|
+ ZipInputStream zipInputStream = new ZipInputStream(bais, Charset.forName("GBK"))) { //指定GBK编码格式
|
|
|
+ // ZipInputStream zipInputStream = new ZipInputStream(bais)) {
|
|
|
+ ZipEntry entry;
|
|
|
+ while ((entry = zipInputStream.getNextEntry()) != null) {
|
|
|
+ try {
|
|
|
+ String entryName = normalizeZipEntryName(entry.getName());
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(entryName) || isIgnoredZipEntry(entryName)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (entry.isDirectory()) {
|
|
|
+ String folderPathInZip = trimTrailingSlash(entryName);
|
|
|
+ ensureFolderImported(folderPathInZip, parentFolderId, parentPath, folderIdCache, stat);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String parentPathInZip = getParentPathInZip(entryName);
|
|
|
+ String dbFolderId = ensureFolderImported(parentPathInZip, parentFolderId, parentPath, folderIdCache, stat);
|
|
|
+
|
|
|
+ String zipFileName = getFileNameFromZipPath(entryName);
|
|
|
+ if (StringUtils.isNotBlank(zipFileName)) {
|
|
|
+ byte[] fileBytes = readZipEntryBytes(zipInputStream);
|
|
|
+ Map<String, Object> fileMap = insertFile(dbFolderId, zipFileName, fileBytes);
|
|
|
+ stat.addFileMap(fileMap);
|
|
|
+ stat.increaseFileCount();
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ zipInputStream.closeEntry();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ logger.info("ZIP文件解析完成,新增文件夹数: {}, 新增文件数: {}", stat.getFolderCount(), stat.getFileCount());
|
|
|
+ return stat;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ private FolderNodeInfo ensureFolderImported(
|
|
|
+ String folderPathInZip,
|
|
|
+ FolderNodeInfo rootFolder,
|
|
|
+ Map<String, FolderNodeInfo> folderCache,
|
|
|
+ ZipImportStat stat) {
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(folderPathInZip)) {
|
|
|
+ return rootFolder;
|
|
|
+ }
|
|
|
+
|
|
|
+ String normalizedFolderPath = trimTrailingSlash(folderPathInZip);
|
|
|
+ if (folderCache.containsKey(normalizedFolderPath)) {
|
|
|
+ return folderCache.get(normalizedFolderPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] names = normalizedFolderPath.split("/");
|
|
|
+ String currentZipPath = "";
|
|
|
+ FolderNodeInfo currentParent = rootFolder;
|
|
|
+
|
|
|
+ for (String name : names) {
|
|
|
+ if (StringUtils.isBlank(name)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ currentZipPath = StringUtils.isBlank(currentZipPath) ? name : currentZipPath + "/" + name;
|
|
|
+
|
|
|
+ if (folderCache.containsKey(currentZipPath)) {
|
|
|
+ currentParent = folderCache.get(currentZipPath);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ FolderNodeInfo existedFolder = querySameLevelFolder(currentParent.getId(), name);
|
|
|
+ if (existedFolder != null) {
|
|
|
+ folderCache.put(currentZipPath, existedFolder);
|
|
|
+ currentParent = existedFolder;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ FolderNodeInfo newFolder = insertFolder(name, currentParent);
|
|
|
+ folderCache.put(currentZipPath, newFolder);
|
|
|
+ stat.increaseFolderCount();
|
|
|
+
|
|
|
+ currentParent = newFolder;
|
|
|
+ }
|
|
|
+
|
|
|
+ return folderCache.get(normalizedFolderPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ private String ensureFolderImported(String folderPathInZip,String rootParentFolderId,String rootParentPath,Map<String, String> folderIdCache,ZipImportStat stat) {
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(folderPathInZip)) {
|
|
|
+ return rootParentFolderId;
|
|
|
+ }
|
|
|
+
|
|
|
+ String normalizedFolderPath = trimTrailingSlash(folderPathInZip);
|
|
|
+ if (folderIdCache.containsKey(normalizedFolderPath)) {
|
|
|
+ return folderIdCache.get(normalizedFolderPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] names = normalizedFolderPath.split("/");
|
|
|
+ String currentZipPath = "";
|
|
|
+ String currentParentId = rootParentFolderId;
|
|
|
+ String currentDbPath = rootParentPath;
|
|
|
+
|
|
|
+ for (String name : names) {
|
|
|
+ if (StringUtils.isBlank(name)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ currentZipPath = StringUtils.isBlank(currentZipPath) ? name : currentZipPath + "/" + name;
|
|
|
+
|
|
|
+ if (folderIdCache.containsKey(currentZipPath)) {
|
|
|
+ currentParentId = folderIdCache.get(currentZipPath);
|
|
|
+ currentDbPath = buildDbPath(currentDbPath, name);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //转化windows读取路径时后缀的/
|
|
|
+ String newDbPath = buildDbPath(currentDbPath, name);
|
|
|
+
|
|
|
+ String newFolderId = insertFolder(name, currentParentId, currentDbPath);
|
|
|
+
|
|
|
+ folderIdCache.put(currentZipPath, newFolderId);
|
|
|
+ stat.increaseFolderCount();
|
|
|
+
|
|
|
+ currentParentId = newFolderId;
|
|
|
+ currentDbPath = newDbPath;
|
|
|
+ }
|
|
|
+
|
|
|
+ return folderIdCache.get(normalizedFolderPath);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ private FolderNodeInfo insertFolder(String folderName, FolderNodeInfo parentFolder) {
|
|
|
+ String folderId = UniqueIdUtil.getId();
|
|
|
+ String folderPath = buildFolderIdPath(parentFolder.getPath(), parentFolder.getId(), folderId);
|
|
|
+ int depth = parentFolder.getDepth() + 1;
|
|
|
+
|
|
|
+ Map<String, Object> map = build(
|
|
|
+ "ID_", folderId,
|
|
|
+ "CATEGORY_KEY_", FOLDER_CATEGORY_KEY,
|
|
|
+ "NAME_", folderName,
|
|
|
+ "TYPE_KEY_", RandomStringUtils.randomAlphabetic(6),
|
|
|
+ "STRU_TYPE_", "1",
|
|
|
+ "PARENT_ID_", parentFolder.getId(),
|
|
|
+ "DEPTH_", depth,
|
|
|
+ "PATH_", folderPath,
|
|
|
+ "IS_LEAF_", "Y",
|
|
|
+ "OWNER_ID_", "0",
|
|
|
+ "TENANT_ID_", "-999",
|
|
|
+ "CREATE_BY_", "1",
|
|
|
+ "CREATE_TIME_", new Date(),
|
|
|
+ "UPDATE_TIME_", new Date()
|
|
|
+ );
|
|
|
+
|
|
|
+ String sql = "INSERT INTO " + FOLDER_TABLE + " ("
|
|
|
+ + "ID_, CATEGORY_KEY_, NAME_, TYPE_KEY_, STRU_TYPE_, PARENT_ID_, DEPTH_, PATH_, "
|
|
|
+ + "IS_LEAF_, OWNER_ID_, TENANT_ID_, CREATE_BY_, CREATE_TIME_, UPDATE_TIME_"
|
|
|
+ + ") VALUES ("
|
|
|
+ + "#{ID_}, #{CATEGORY_KEY_}, #{NAME_}, #{TYPE_KEY_}, #{STRU_TYPE_}, #{PARENT_ID_}, #{DEPTH_}, #{PATH_}, "
|
|
|
+ + "#{IS_LEAF_}, #{OWNER_ID_}, #{TENANT_ID_}, #{CREATE_BY_}, #{CREATE_TIME_}, #{UPDATE_TIME_}"
|
|
|
+ + ")";
|
|
|
+
|
|
|
+ try {
|
|
|
+ commonDao.executeOfMap(sql, map);
|
|
|
+ updateFolderNotLeaf(parentFolder.getId());
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.warn("添加文件夹数据失败: {}", map, e);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+
|
|
|
+ FolderNodeInfo node = new FolderNodeInfo();
|
|
|
+ node.setId(folderId);
|
|
|
+ node.setPath(folderPath);
|
|
|
+ node.setDepth(depth);
|
|
|
+
|
|
|
+ logger.info("插入文件夹: id={}, name={}, parentId={}, path={}, depth={}",
|
|
|
+ folderId, folderName, parentFolder.getId(), folderPath, depth);
|
|
|
+ return node;
|
|
|
+ }
|
|
|
+
|
|
|
+ private FolderNodeInfo querySameLevelFolder(String parentId, String folderName) {
|
|
|
+ String sql = "SELECT ID_, PATH_, DEPTH_ FROM " + FOLDER_TABLE
|
|
|
+ + " WHERE PARENT_ID_ = #{p0}"
|
|
|
+ + " AND NAME_ = #{p1}"
|
|
|
+ + " AND CATEGORY_KEY_ = #{p2}"
|
|
|
+ + " LIMIT 1";
|
|
|
+
|
|
|
+ List<?> list = commonDao.query(sql, new Object[] { parentId, folderName, FOLDER_CATEGORY_KEY });
|
|
|
+
|
|
|
+ if (list == null || list.isEmpty() || list.get(0) == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return toFolderNodeInfo(list.get(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ private FolderNodeInfo queryFolderNodeById(String folderId) {
|
|
|
+ String sql = "SELECT ID_, PATH_, DEPTH_ FROM " + FOLDER_TABLE + " WHERE ID_ = #{p0}";
|
|
|
+ List<?> list = commonDao.query(sql, new Object[] { folderId });
|
|
|
+
|
|
|
+ if (list == null || list.isEmpty() || list.get(0) == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return toFolderNodeInfo(list.get(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateFolderNotLeaf(String folderId) {
|
|
|
+ if (StringUtils.isBlank(folderId)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String sql = "UPDATE " + FOLDER_TABLE
|
|
|
+ + " SET IS_LEAF_ = #{IS_LEAF_}, UPDATE_TIME_ = #{UPDATE_TIME_}"
|
|
|
+ + " WHERE ID_ = #{ID_}";
|
|
|
+
|
|
|
+ Map<String, Object> params = build(
|
|
|
+ "ID_", folderId,
|
|
|
+ "IS_LEAF_", "N",
|
|
|
+ "UPDATE_TIME_", new Date()
|
|
|
+ );
|
|
|
+
|
|
|
+ commonDao.executeOfMap(sql, params);
|
|
|
+ }
|
|
|
+/*
|
|
|
+ private String buildFolderIdPath(String parentPath, String parentId, String currentId) {
|
|
|
+ String basePath = parentPath;
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(basePath)) {
|
|
|
+ basePath = parentId;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(basePath)) {
|
|
|
+ return currentId;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (basePath.endsWith("/")) {
|
|
|
+ return basePath + currentId;
|
|
|
+ }
|
|
|
+
|
|
|
+ return basePath + "/" + currentId;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ private String buildFolderIdPath(String parentPath, String parentId, String currentId) {
|
|
|
+ String basePath = parentPath;
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(basePath)) {
|
|
|
+ basePath = parentId;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(basePath)) {
|
|
|
+ return currentId + ".";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!basePath.endsWith(".")) {
|
|
|
+ basePath = basePath + ".";
|
|
|
+ }
|
|
|
+
|
|
|
+ return basePath + currentId + ".";
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ private String insertFolder(String folderName, String parentId, String folderPath) {
|
|
|
+ String folderId = UniqueIdUtil.getId(); //当前节点的id,需要拼接在path上,防止前段后续读取不到层级结构
|
|
|
+ String fileType = "FILE_TYPE"; //文件固定分类
|
|
|
+ //先加数据,后面再来考录path的问题
|
|
|
+ Map<String, Object> map = build("ID_", folderId,
|
|
|
+ "CATEGORY_KEY_", fileType,
|
|
|
+ "name_", folderName,
|
|
|
+ "type_key_", RandomStringUtils.randomAlphabetic(6),
|
|
|
+ "stru_type_", "1",
|
|
|
+ "PARENT_ID_", parentId,
|
|
|
+ "DEPTH_", 6,
|
|
|
+ "PATH_", "",
|
|
|
+ "IS_LEAF_", "Y",
|
|
|
+ "OWNER_ID_", "0",
|
|
|
+ "TENANT_ID_", "-999",
|
|
|
+ "CREATE_BY_", "1",
|
|
|
+ "CREATE_TIME_",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
|
|
|
+ "UPDATE_TIME_",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
|
|
+ try {
|
|
|
+ commonDao.execute(this.buildInsertSql(map, "ibps_cat_type"));
|
|
|
+ }catch (Exception e){
|
|
|
+ logger.warn("添加文件夹数据失败:"+map);
|
|
|
+ }
|
|
|
+ logger.info("插入文件夹: id={}, name={}, parentId={}, path={}", folderId, folderName, parentId, folderPath);
|
|
|
+ return folderId;
|
|
|
+ }*/
|
|
|
+
|
|
|
+
|
|
|
+ private FolderNodeInfo toFolderNodeInfo(Object row) {
|
|
|
+ if (!(row instanceof Map)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<?, ?> rowMap = (Map<?, ?>) row;
|
|
|
+
|
|
|
+ FolderNodeInfo node = new FolderNodeInfo();
|
|
|
+ node.setId(toStringValue(getMapValue(rowMap, "ID_")));
|
|
|
+ node.setPath(toStringValue(getMapValue(rowMap, "PATH_")));
|
|
|
+ node.setDepth(toIntValue(getMapValue(rowMap, "DEPTH_")));
|
|
|
+
|
|
|
+ return StringUtils.isBlank(node.getId()) ? null : node;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Object getMapValue(Map<?, ?> map, String key) {
|
|
|
+ Object value = map.get(key);
|
|
|
+ if (value != null) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ value = map.get(key.toLowerCase());
|
|
|
+ if (value != null) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ return map.get(key.toUpperCase());
|
|
|
+ }
|
|
|
+
|
|
|
+ private String toStringValue(Object value) {
|
|
|
+ return value == null ? "" : String.valueOf(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int toIntValue(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (value instanceof Number) {
|
|
|
+ return ((Number) value).intValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ return Integer.parseInt(String.valueOf(value));
|
|
|
+ } catch (Exception e) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private byte[] readZipEntryBytes(ZipInputStream zipInputStream) throws IOException {
|
|
|
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
+ byte[] buffer = new byte[8192];
|
|
|
+ int len;
|
|
|
+
|
|
|
+ while ((len = zipInputStream.read(buffer)) != -1) {
|
|
|
+ outputStream.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+
|
|
|
+ return outputStream.toByteArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> insertFile(String folderId, String fileName, byte[] fileBytes) throws IOException {
|
|
|
+ String fileId = UniqueIdUtil.getId();
|
|
|
+
|
|
|
+ Map<String, String> fileNameInfo = parseFileNameInfo(fileName);
|
|
|
+ String fileCode = fileNameInfo.get(KEY_WEN_JIAN_HAO);
|
|
|
+ String realFileName = fileNameInfo.get(KEY_WEN_JIAN_MING);
|
|
|
+ AttachmentPo attachmentPo = new AttachmentPo();
|
|
|
+ String attachmentId ="";
|
|
|
+ try {
|
|
|
+ this.getUploadService();
|
|
|
+ Map<String, Object> uploadParams = new HashMap<>();
|
|
|
+ uploadParams.put(FileParam.ORIGINAL_FILE_NAME, fileName);
|
|
|
+ uploadParams.put(FileParam.FILE_SIZE, fileBytes == null ? 0L : Long.valueOf(fileBytes.length));
|
|
|
+ uploadParams.put(FileParam.CUR_USER_ID, ContextUtil.getCurrentUser().getUserId());
|
|
|
+ uploadParams.put(FileParam.CUR_USER_ACCOUNT, ContextUtil.getCurrentUser().getAccount());
|
|
|
+ uploadParams.put(FileParam.CUR_USER_NAME, ContextUtil.getCurrentUser().getFullname());
|
|
|
+
|
|
|
+ attachmentPo = uploadService.uploadFile(new ByteArrayInputStream(fileBytes), uploadParams);
|
|
|
+ if (attachmentPo == null || StringUtils.isBlank(attachmentPo.getId())) {
|
|
|
+ throw new RuntimeException("解压文件上传失败: " + fileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ attachmentId = attachmentPo.getId();
|
|
|
+ }catch (Exception e){
|
|
|
+ logger.warn("上传失败");
|
|
|
+ }
|
|
|
+ Map<String, Object> params = build("id_", fileId,
|
|
|
+ "wen_jian_ming_che", attachmentPo.getFileName(),
|
|
|
+ "wen_jian_bian_hao", fileCode,
|
|
|
+ "wen_jian_fen_lei_",folderId,
|
|
|
+ "attachmentid", attachmentId);
|
|
|
+ try {
|
|
|
+ commonDao.execute(this.buildInsertSql(params, "t_filetable"));
|
|
|
+ }catch (Exception e){
|
|
|
+ logger.warn("添加文件表数据失败");
|
|
|
+ }
|
|
|
+ Map<String, Object> fileResultMap = build(
|
|
|
+ KEY_WEN_JIAN_ID, fileId,
|
|
|
+ KEY_WEN_JIAN_JIA_ID, folderId,
|
|
|
+ KEY_WEN_JIAN_MING, realFileName,
|
|
|
+ KEY_WEN_JIAN_HAO, fileCode,
|
|
|
+ "attachment_id_", attachmentId
|
|
|
+ );
|
|
|
+
|
|
|
+ logger.info("插入文件: id={}, folderId={}, attachmentId={}, fileName={}, fileCode={}",
|
|
|
+ fileId, folderId, attachmentId, realFileName, fileCode);
|
|
|
+
|
|
|
+ return fileResultMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> parseFileNameInfo(String fileName) {
|
|
|
+ Map<String, String> result = new HashMap<>();
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(fileName)) {
|
|
|
+ result.put(KEY_WEN_JIAN_HAO, "");
|
|
|
+ result.put(KEY_WEN_JIAN_MING, "");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ String normalizedFileName = fileName.trim();
|
|
|
+ String[] parts = normalizedFileName.split("\\s+", 2);
|
|
|
+
|
|
|
+ if (parts.length < 2 || StringUtils.isBlank(parts[0]) || StringUtils.isBlank(parts[1])) {
|
|
|
+ result.put(KEY_WEN_JIAN_HAO, "");
|
|
|
+ result.put(KEY_WEN_JIAN_MING, normalizedFileName);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ result.put(KEY_WEN_JIAN_HAO, parts[0].trim());
|
|
|
+ result.put(KEY_WEN_JIAN_MING, parts[1].trim());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+/*
|
|
|
+ private String queryFolderPathById(String folderId) {
|
|
|
+ String sql = "SELECT path_ FROM " + FOLDER_TABLE + " WHERE id_ = #{p0}";
|
|
|
+ List<?> list = commonDao.query(sql, new Object[] { folderId });
|
|
|
+
|
|
|
+ if (list == null || list.isEmpty() || list.get(0) == null) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ Object row = list.get(0);
|
|
|
+ if (row instanceof Map) {
|
|
|
+ Map<?, ?> rowMap = (Map<?, ?>) row;
|
|
|
+ Object path = rowMap.get("path_");
|
|
|
+ if (path == null) {
|
|
|
+ path = rowMap.get("PATH_");
|
|
|
+ }
|
|
|
+ return path == null ? "" : String.valueOf(path);
|
|
|
+ }
|
|
|
+
|
|
|
+ return String.valueOf(row);
|
|
|
+ }
|
|
|
+*/
|
|
|
+
|
|
|
+ private String normalizeZipEntryName(String entryName) {
|
|
|
+ if (StringUtils.isBlank(entryName)) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ String normalized = entryName.replace("\\", "/").trim();
|
|
|
+
|
|
|
+ while (normalized.startsWith("/")) {
|
|
|
+ normalized = normalized.substring(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (normalized.contains(":")) {
|
|
|
+ throw new IllegalArgumentException("ZIP条目路径非法: " + entryName);
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] parts = normalized.split("/");
|
|
|
+ for (String part : parts) {
|
|
|
+ if ("..".equals(part) || ".".equals(part)) {
|
|
|
+ throw new IllegalArgumentException("ZIP条目路径非法: " + entryName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return normalized;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isIgnoredZipEntry(String entryName) {
|
|
|
+ return entryName.startsWith("__MACOSX/")
|
|
|
+ || entryName.endsWith(".DS_Store")
|
|
|
+ || entryName.contains("/.DS_Store");
|
|
|
+ }
|
|
|
+
|
|
|
+ private String trimTrailingSlash(String path) {
|
|
|
+ if (StringUtils.isBlank(path)) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ String result = path;
|
|
|
+ while (result.endsWith("/")) {
|
|
|
+ result = result.substring(0, result.length() - 1);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getParentPathInZip(String entryName) {
|
|
|
+ int index = entryName.lastIndexOf('/');
|
|
|
+ if (index < 0) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return entryName.substring(0, index);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getFileNameFromZipPath(String entryName) {
|
|
|
+ int index = entryName.lastIndexOf('/');
|
|
|
+ if (index < 0) {
|
|
|
+ return entryName;
|
|
|
+ }
|
|
|
+ return entryName.substring(index + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ private String buildDbPath(String parentPath, String name) {
|
|
|
+ if (StringUtils.isBlank(parentPath)) {
|
|
|
+ return "/" + name;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (parentPath.endsWith("/")) {
|
|
|
+ return parentPath + name;
|
|
|
+ }
|
|
|
+
|
|
|
+ return parentPath + "/" + name;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ public Map<String,Object> build(Object... keyValues){
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ for (int i = 0; i < keyValues.length; i += 2) {
|
|
|
+ map.put((String) keyValues[i], keyValues[i + 1]);
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String buildInsertSql(Map<String, Object> map , String tableName) throws Exception {
|
|
|
+
|
|
|
+ StringBuilder sql = new StringBuilder("insert into "+tableName+" (");
|
|
|
+ for (Object key : map.keySet()) {
|
|
|
+ sql.append(key).append(",");
|
|
|
+ }
|
|
|
+ sql.delete(sql.length()-1,sql.length());
|
|
|
+ sql.append(") values(");
|
|
|
+ for (Object val : map.values()) {
|
|
|
+ sql.append("'").append(val).append("'").append(",");
|
|
|
+ }
|
|
|
+ sql.delete(sql.length()-1,sql.length());
|
|
|
+ sql.append(")");
|
|
|
+ return sql.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
@ApiOperation(value = "文件下载", notes = "文件下载")
|
|
|
@Override
|
|
|
public void download(
|