|
|
@@ -1,14 +1,20 @@
|
|
|
package com.xunmei.file.service;
|
|
|
|
|
|
-import cn.hutool.Hutool;
|
|
|
-import cn.hutool.core.codec.Base64;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.lowagie.text.*;
|
|
|
import com.lowagie.text.pdf.BaseFont;
|
|
|
import com.lowagie.text.pdf.PdfPCell;
|
|
|
import com.lowagie.text.pdf.PdfPTable;
|
|
|
import com.lowagie.text.pdf.PdfWriter;
|
|
|
+import com.xunmei.common.core.domain.IdName;
|
|
|
+import com.xunmei.common.core.domain.registerbook.dto.CoreRegisterBookPdfExportDto;
|
|
|
+import com.xunmei.common.core.domain.registerbook.dto.ExportPdfDto;
|
|
|
+import com.xunmei.common.core.domain.registerbook.vo.CoreRegisterBookPdfPageVo;
|
|
|
+import com.xunmei.common.core.domain.registerbook.vo.PdfToZipTempVo;
|
|
|
+import com.xunmei.common.core.enums.RegisterBookType;
|
|
|
+import com.xunmei.common.core.utils.DateHelper;
|
|
|
import com.xunmei.common.core.utils.uuid.UUID;
|
|
|
import com.xunmei.file.utils.FileDownUtils;
|
|
|
import com.xunmei.file.utils.FileUploadUtils;
|
|
|
@@ -16,38 +22,49 @@ import com.xunmei.file.utils.PdfUtil;
|
|
|
import com.xunmei.file.vo.FileBase64Vo;
|
|
|
import com.xunmei.file.vo.ItextPdfTableVo;
|
|
|
import com.xunmei.file.vo.PdfFilePathVo;
|
|
|
+import io.netty.util.internal.StringUtil;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.tools.zip.ZipEntry;
|
|
|
+import org.apache.tools.zip.ZipOutputStream;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.context.annotation.Primary;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.http.HttpHeaders;
|
|
|
import org.springframework.http.MediaType;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
+import javax.servlet.ServletOutputStream;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
import java.io.*;
|
|
|
import java.net.URLDecoder;
|
|
|
+import java.net.URLEncoder;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.Map;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.util.List;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.CountDownLatch;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
/**
|
|
|
* 本地文件存储
|
|
|
*
|
|
|
* @author xunmei
|
|
|
*/
|
|
|
+
|
|
|
@Primary
|
|
|
@Service
|
|
|
public class LocalSysFileServiceImpl implements ISysFileService {
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(LocalSysFileServiceImpl.class);
|
|
|
+ public static final String TEMP_DIR_NAME = "registerBookPdfBatchExportTempDir";
|
|
|
+ @Autowired
|
|
|
+ RedisTemplate redisTemplate;
|
|
|
|
|
|
- /**
|
|
|
- * 上传文件存储在本地的根路径
|
|
|
- */
|
|
|
@Value("${file.path}")
|
|
|
private String localFilePath;
|
|
|
|
|
|
@@ -486,4 +503,150 @@ public class LocalSysFileServiceImpl implements ISysFileService {
|
|
|
|
|
|
document.close();
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String absolutePath(String path) {
|
|
|
+ if (ObjectUtil.isEmpty(path)) {
|
|
|
+ return StringUtil.EMPTY_STRING;
|
|
|
+ }
|
|
|
+ if (path.startsWith(this.localFilePath)) {
|
|
|
+ return path;
|
|
|
+ }
|
|
|
+ if (path.startsWith(this.prefix)) {
|
|
|
+ return this.localFilePath + path.substring(this.prefix.length());
|
|
|
+ }
|
|
|
+ return StringUtil.EMPTY_STRING;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public InputStream getFileStream(String path) throws IOException {
|
|
|
+ String absolutePath = this.absolutePath(path);
|
|
|
+ File file = new File(absolutePath);
|
|
|
+ return Files.newInputStream(file.toPath());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void registerBookCompressPdf(ExportPdfDto pdfDto,HttpServletResponse response) {
|
|
|
+ if (ObjectUtil.isEmpty(pdfDto.getGuid())) {
|
|
|
+ pdfDto.setGuid(cn.hutool.core.lang.UUID.fastUUID().toString());
|
|
|
+ }
|
|
|
+ final List<CoreRegisterBookPdfPageVo> registerBookPdfList = pdfDto.getRegisterBookPdfList();
|
|
|
+ try {
|
|
|
+ String zipName = URLEncoder.encode(pdfDto.getFileName() + DateHelper.getDateString(new Date()) + ".zip", "UTF-8");
|
|
|
+ final CountDownLatch count = new CountDownLatch(registerBookPdfList.size());
|
|
|
+ ServletOutputStream outputStream = response.getOutputStream();
|
|
|
+ ZipOutputStream zos = new ZipOutputStream(outputStream);
|
|
|
+ response.setContentType("application/octet-stream");
|
|
|
+ response.setHeader("Content-Disposition", "attachment; filename=" + zipName);
|
|
|
+ List<PdfToZipTempVo> pdfToZipTempVoList = registerBookPdfList.parallelStream().map(pdf -> {
|
|
|
+ return resolve(pdf, pdfDto, count);
|
|
|
+ }).filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ count.await();
|
|
|
+ pdfToZipTempVoList.removeIf(pdfToZipTempVo -> !FileUtil.exist(pdfToZipTempVo.getFile()));
|
|
|
+ log.info("登记簿全部下载完成,开始压缩文件,数量:{}", pdfToZipTempVoList.size());
|
|
|
+ for (PdfToZipTempVo tempVo : pdfToZipTempVoList) {
|
|
|
+ log.info("当前开始处理第{}个文件 ", pdfToZipTempVoList.indexOf(tempVo) + 1);
|
|
|
+ deal(zos, pdfDto, tempVo);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ outputStream.flush();
|
|
|
+ outputStream.close();
|
|
|
+
|
|
|
+ log.info("登记簿批量导出压缩文件完成,文件数量:{}", pdfToZipTempVoList.size());
|
|
|
+ } catch (Throwable e) {
|
|
|
+ String errMsg = String.format("登记簿导出失败:%s", e);
|
|
|
+ log.error(errMsg);
|
|
|
+ } finally {
|
|
|
+ final File temp = new File(TEMP_DIR_NAME);
|
|
|
+ if (temp.exists()) {
|
|
|
+ FileUtil.del(temp);
|
|
|
+ log.info("临时目录已删除");
|
|
|
+ }
|
|
|
+ // redisTemplate.delete(pdfDto.getGuid());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public PdfToZipTempVo resolve(CoreRegisterBookPdfPageVo pdf, ExportPdfDto pdfDto, CountDownLatch count) {
|
|
|
+
|
|
|
+ final File temp = new File(TEMP_DIR_NAME);
|
|
|
+ if (!temp.exists()) {
|
|
|
+ temp.mkdirs();
|
|
|
+ }
|
|
|
+ InputStream inputStream;
|
|
|
+ try {
|
|
|
+
|
|
|
+ inputStream = getFileStream(pdf.getFileUrl());
|
|
|
+ if (pdfDto != null) {
|
|
|
+ redisTemplate.opsForValue().increment(pdfDto.getGuid(), 9);
|
|
|
+ }
|
|
|
+ if (ObjectUtil.isEmpty(inputStream)) {
|
|
|
+ log.error("登记簿导出失败,文件不存在,文件名:{}", pdf.getFileUrl());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ final String pdfFileName = pdf.getFileName();
|
|
|
+ final PdfToZipTempVo tempVo = new PdfToZipTempVo();
|
|
|
+ //tempVo.setBytes(bytes);
|
|
|
+ tempVo.setFileName(pdfFileName);
|
|
|
+ tempVo.setOrgId(pdf.getOrgId());
|
|
|
+ tempVo.setOrgName(pdf.getOrgName());
|
|
|
+ tempVo.setRegisterBookType(RegisterBookType.getEnums(pdf.getRegisterBookType()));
|
|
|
+
|
|
|
+ final File file = new File(temp + File.separator + pdfFileName);
|
|
|
+ final FileOutputStream outputStream = new FileOutputStream(file);
|
|
|
+ byte[] buffer = new byte[4096];
|
|
|
+ int len;
|
|
|
+ while ((len = inputStream.read(buffer)) > 0) {
|
|
|
+ outputStream.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+ outputStream.close();
|
|
|
+ inputStream.close();
|
|
|
+ tempVo.setFile(file);
|
|
|
+ final List<IdName<Long, String>> idNameList = pdf.getOrgList();
|
|
|
+ if (ObjectUtil.isEmpty(idNameList)) {
|
|
|
+ tempVo.setEntryName(File.separator + RegisterBookType.getEnums(pdf.getRegisterBookType()).getText() + File.separator + pdfFileName);
|
|
|
+ return tempVo;
|
|
|
+ }
|
|
|
+ StringJoiner stringJoiner = new StringJoiner(File.separator);
|
|
|
+ for (IdName<Long, String> org : idNameList) {
|
|
|
+ stringJoiner.add(org.getName());
|
|
|
+ if (idNameList.lastIndexOf(org) == idNameList.size() - 1) {
|
|
|
+ stringJoiner.add(RegisterBookType.getEnums(pdf.getRegisterBookType()).getText() + File.separator + pdfFileName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tempVo.setEntryName(stringJoiner.toString());
|
|
|
+ return tempVo;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("读取文件失败", e);
|
|
|
+ return null;
|
|
|
+ } finally {
|
|
|
+ count.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void deal(ZipOutputStream zos, ExportPdfDto pdfDto, PdfToZipTempVo zipTempVo) throws Throwable {
|
|
|
+ zos.setEncoding("GBK");
|
|
|
+ FileInputStream fileInputStream = new FileInputStream(zipTempVo.getFile());
|
|
|
+ zos.putNextEntry(new ZipEntry(zipTempVo.getEntryName()));
|
|
|
+ byte[] buffer = new byte[4096];
|
|
|
+ int len;
|
|
|
+ while ((len = fileInputStream.read(buffer)) > 0) {
|
|
|
+ zos.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+ fileInputStream.close();
|
|
|
+ if (pdfDto != null) {
|
|
|
+ redisTemplate.opsForValue().increment(pdfDto.getGuid(), 9);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void cutFileCompress(CoreRegisterBookPdfExportDto exportDto) {
|
|
|
+
|
|
|
+ }
|
|
|
}
|