|
|
|
@ -1,15 +1,26 @@
|
|
|
|
|
package com.palnet.comn.utils; |
|
|
|
|
|
|
|
|
|
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.OutputStream; |
|
|
|
|
import java.io.StringReader; |
|
|
|
|
import com.itextpdf.html2pdf.ConverterProperties; |
|
|
|
|
import com.itextpdf.html2pdf.HtmlConverter; |
|
|
|
|
import com.itextpdf.io.font.PdfEncodings; |
|
|
|
|
import com.itextpdf.kernel.pdf.PdfDocument; |
|
|
|
|
import com.itextpdf.kernel.pdf.PdfWriter; |
|
|
|
|
import com.itextpdf.layout.font.FontProvider; |
|
|
|
|
import com.palnet.biz.api.comn.file.model.PdfBaseModel; |
|
|
|
|
import com.palnet.biz.jpa.entity.ComFileBas; |
|
|
|
|
import com.palnet.comn.code.ErrorCode; |
|
|
|
|
import com.palnet.comn.exception.CustomException; |
|
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
import org.thymeleaf.TemplateEngine; |
|
|
|
|
import org.thymeleaf.context.Context; |
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
|
import java.io.*; |
|
|
|
|
import java.net.URLEncoder; |
|
|
|
|
import java.nio.charset.Charset; |
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
|
import java.nio.file.Files; |
|
|
|
|
import java.nio.file.Paths; |
|
|
|
|
import java.time.Instant; |
|
|
|
@ -17,44 +28,13 @@ import java.util.Map;
|
|
|
|
|
import java.util.Map.Entry; |
|
|
|
|
import java.util.Objects; |
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
import org.thymeleaf.TemplateEngine; |
|
|
|
|
import org.thymeleaf.context.Context; |
|
|
|
|
|
|
|
|
|
import com.itextpdf.text.Document; |
|
|
|
|
import com.itextpdf.text.DocumentException; |
|
|
|
|
import com.itextpdf.text.pdf.PdfWriter; |
|
|
|
|
import com.itextpdf.tool.xml.XMLWorker; |
|
|
|
|
import com.itextpdf.tool.xml.XMLWorkerFontProvider; |
|
|
|
|
import com.itextpdf.tool.xml.XMLWorkerHelper; |
|
|
|
|
import com.itextpdf.tool.xml.css.CssFile; |
|
|
|
|
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver; |
|
|
|
|
import com.itextpdf.tool.xml.html.CssAppliers; |
|
|
|
|
import com.itextpdf.tool.xml.html.CssAppliersImpl; |
|
|
|
|
import com.itextpdf.tool.xml.html.Tags; |
|
|
|
|
import com.itextpdf.tool.xml.parser.XMLParser; |
|
|
|
|
import com.itextpdf.tool.xml.pipeline.css.CSSResolver; |
|
|
|
|
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline; |
|
|
|
|
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline; |
|
|
|
|
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline; |
|
|
|
|
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext; |
|
|
|
|
import com.palnet.biz.api.bas.flight.template.vo.PdfBaseVO; |
|
|
|
|
import com.palnet.biz.jpa.entity.ComFileBas; |
|
|
|
|
import com.palnet.comn.code.ErrorCode; |
|
|
|
|
import com.palnet.comn.exception.CustomException; |
|
|
|
|
|
|
|
|
|
@Slf4j |
|
|
|
|
@RequiredArgsConstructor |
|
|
|
|
@Component |
|
|
|
|
public class PdfUtils { |
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
private HttpServletResponse response; |
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
private TemplateEngine templateEngine; |
|
|
|
|
private final HttpServletResponse response; |
|
|
|
|
private final TemplateEngine templateEngine; |
|
|
|
|
|
|
|
|
|
@Value("${base-url}") |
|
|
|
|
private String BASE_PATH; |
|
|
|
@ -64,20 +44,21 @@ public class PdfUtils {
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Thymeleaf HTML 파일을 데이터 바인딩하여 String으로 변환 |
|
|
|
|
* |
|
|
|
|
* @param <T> |
|
|
|
|
* @param pdfDto |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public <T extends PdfBaseVO> String getHtmlToString(T pdfDto){ |
|
|
|
|
public <T extends PdfBaseModel> String getHtmlToString(T pdfDto) { |
|
|
|
|
|
|
|
|
|
Map<String, Object> param = pdfDto.getParam(); |
|
|
|
|
|
|
|
|
|
// Thymeleaf 방식 html에 입힐 데이터 바인딩
|
|
|
|
|
Context context = new Context(); |
|
|
|
|
Context context = new Context(); |
|
|
|
|
|
|
|
|
|
for(Entry<String, Object> entry : param.entrySet()){ |
|
|
|
|
for (Entry<String, Object> entry : param.entrySet()) { |
|
|
|
|
String key = entry.getKey(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context.setVariable(key, param.get(key)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -90,86 +71,51 @@ public class PdfUtils {
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* HTML 태그로 이루어진 String값을 PDF로 변환 |
|
|
|
|
* |
|
|
|
|
* @param htmlContent |
|
|
|
|
* @param fileName |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public ComFileBas generatePDF(String htmlContent, String fileName){ |
|
|
|
|
|
|
|
|
|
// PDF 용지 설정하기
|
|
|
|
|
Document pdfDocument = new Document(); |
|
|
|
|
public ComFileBas generatePDF(String htmlContent, String fileName) { |
|
|
|
|
|
|
|
|
|
ComFileBas result = new ComFileBas(); |
|
|
|
|
|
|
|
|
|
String pdfPath = new StringBuilder() |
|
|
|
|
.append(this.BASE_PATH) |
|
|
|
|
.append(InstantUtils.toDateString(Instant.now()).replace("-", "")) |
|
|
|
|
.append("/").toString(); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
|
|
// 폴더 생성
|
|
|
|
|
new File(pdfPath).mkdirs(); |
|
|
|
|
|
|
|
|
|
// File 저장 기본경로는 main 아래로 기본으로 잡힘
|
|
|
|
|
PdfWriter writer = PdfWriter.getInstance(pdfDocument, new FileOutputStream(pdfPath + fileName)); |
|
|
|
|
writer.setInitialLeading(12.5f); |
|
|
|
|
|
|
|
|
|
pdfDocument.open(); |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
CSS 설정 |
|
|
|
|
TODO : CSS 파일이 따로 있을시 임포트해주는 방법, CSS 파일 적용은 필수는 아니지만, 글꼴 적용은 꼭해야만 함 |
|
|
|
|
jar변환 시 CSS파일을 못 찾을수도 있어서 InputStream 사용 |
|
|
|
|
CSS의 색깔은 키워드로 표기 X, #e73a3a 등 16진법으로 표기 해야함 |
|
|
|
|
*/ |
|
|
|
|
InputStream cssStream = getClass().getClassLoader().getResourceAsStream("static/css/pdf.css"); |
|
|
|
|
CssFile cssFile = XMLWorkerHelper.getCSS(cssStream); |
|
|
|
|
CSSResolver cssResolver = new StyleAttrCSSResolver(); |
|
|
|
|
cssResolver.addCss(cssFile); |
|
|
|
|
|
|
|
|
|
// Font 설정
|
|
|
|
|
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS); |
|
|
|
|
fontProvider.register("static/font/NanumGothic.ttf", "NanumGothic"); |
|
|
|
|
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider); |
|
|
|
|
|
|
|
|
|
// XML Worker에 넣을 PipeLine객체 생성, CssResolverPipeline 이 객체를 최종적으로 넣어야 Font,Css가 적용됨
|
|
|
|
|
HtmlPipelineContext htmlPipelineContext = new HtmlPipelineContext(cssAppliers); |
|
|
|
|
htmlPipelineContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); |
|
|
|
|
|
|
|
|
|
PdfWriterPipeline pdfWriterPipeline = new PdfWriterPipeline(pdfDocument, writer); |
|
|
|
|
HtmlPipeline htmlPipeline = new HtmlPipeline(htmlPipelineContext, pdfWriterPipeline); |
|
|
|
|
CssResolverPipeline cssResolverPipeline = new CssResolverPipeline(cssResolver, htmlPipeline); |
|
|
|
|
|
|
|
|
|
StringReader stringReader = new StringReader(htmlContent); |
|
|
|
|
|
|
|
|
|
XMLWorker xmlWorker = new XMLWorker(cssResolverPipeline, true); |
|
|
|
|
XMLParser xmlParser = new XMLParser(xmlWorker, Charset.forName("UTF-8")); |
|
|
|
|
|
|
|
|
|
xmlParser.parse(stringReader); |
|
|
|
|
String pdfPath = this.BASE_PATH + InstantUtils.toDateStringByFormat(Instant.now(), "yyyyMMdd") + "/"; |
|
|
|
|
String pdfFilePath = pdfPath + fileName; |
|
|
|
|
|
|
|
|
|
File path = new File(pdfPath); |
|
|
|
|
boolean mkdirs = path.mkdirs(); |
|
|
|
|
log.debug(">>> 폴더 생성여부 : {}", mkdirs); |
|
|
|
|
|
|
|
|
|
// PDF 생성
|
|
|
|
|
try (FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath)) { |
|
|
|
|
PdfWriter pdfWriter = new PdfWriter(fileOutputStream); |
|
|
|
|
PdfDocument pdfDoc = new PdfDocument(pdfWriter); |
|
|
|
|
ConverterProperties converterProperties = new ConverterProperties(); |
|
|
|
|
|
|
|
|
|
// FontProvider를 사용하여 한글 폰트 지정
|
|
|
|
|
FontProvider fontProvider = new FontProvider(); |
|
|
|
|
fontProvider.addFont("templates/fonts/NanumGothic.ttf", PdfEncodings.IDENTITY_H); |
|
|
|
|
converterProperties.setFontProvider(fontProvider); |
|
|
|
|
|
|
|
|
|
HtmlConverter.convertToPdf(htmlContent, pdfDoc, converterProperties); |
|
|
|
|
|
|
|
|
|
} catch (IOException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
} catch (DocumentException e){ |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
} catch (Exception e){ |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
} |
|
|
|
|
finally{ |
|
|
|
|
pdfDocument.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
throw new RuntimeException(e); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
result.setFileGroupNo(0); |
|
|
|
|
result.setFilePath(pdfPath); |
|
|
|
|
result.setFileExt(this.FILE_EXTENSION); |
|
|
|
|
result.setCreateDt(Instant.now()); |
|
|
|
|
result.setCreateDt(Instant.now()); |
|
|
|
|
result.setFileSaveNm(fileName); |
|
|
|
|
result.setFileOriNm(fileName); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
try { |
|
|
|
|
String filePath = result.getFileOriNm(); |
|
|
|
|
long fileSize = Files.size(Paths.get(pdfPath + filePath)) / 1024; |
|
|
|
|
|
|
|
|
|
if(fileSize >= 0) result.setFileSize(String.valueOf(fileSize)); |
|
|
|
|
if (fileSize >= 0) result.setFileSize(String.valueOf(fileSize)); |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
} |
|
|
|
@ -179,52 +125,53 @@ public class PdfUtils {
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 파일 Download |
|
|
|
|
* |
|
|
|
|
* @param comFileBas |
|
|
|
|
*/ |
|
|
|
|
public void fileDownload(ComFileBas comFileBas){ |
|
|
|
|
public void fileDownload(ComFileBas comFileBas) { |
|
|
|
|
InputStream inputStream = null; |
|
|
|
|
OutputStream outputStream = null; |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
File pdfFile = new File(comFileBas.getFilePath() + comFileBas.getFileSaveNm()); |
|
|
|
|
inputStream = new FileInputStream(pdfFile); |
|
|
|
|
File pdfFile = new File(comFileBas.getFilePath() + comFileBas.getFileSaveNm()); |
|
|
|
|
inputStream = new FileInputStream(pdfFile); |
|
|
|
|
|
|
|
|
|
String fileOriName = comFileBas.getFileOriNm(); |
|
|
|
|
fileOriName = URLEncoder.encode(comFileBas.getFileOriNm(), "UTF-8"); |
|
|
|
|
fileOriName = URLEncoder.encode(comFileBas.getFileOriNm(), StandardCharsets.UTF_8); |
|
|
|
|
|
|
|
|
|
response.setContentType("application/octet-stream"); |
|
|
|
|
response.setCharacterEncoding("UTF-8"); |
|
|
|
|
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileOriName + "\""); |
|
|
|
|
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileOriName + "\""); |
|
|
|
|
// response.setContentLengthLong(Long.parseLong(comFileBas.getFileSize()));
|
|
|
|
|
// response.setStatus(HttpServletResponse.SC_OK);
|
|
|
|
|
|
|
|
|
|
outputStream = response.getOutputStream(); |
|
|
|
|
|
|
|
|
|
byte[] buffer = new byte[1024]; //1KB 설정
|
|
|
|
|
int length; |
|
|
|
|
|
|
|
|
|
while((length = inputStream.read(buffer)) != -1) { |
|
|
|
|
outputStream.write(buffer); |
|
|
|
|
} |
|
|
|
|
int length; |
|
|
|
|
|
|
|
|
|
while ((length = inputStream.read(buffer)) != -1) { |
|
|
|
|
outputStream.write(buffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} catch (FileNotFoundException e) { |
|
|
|
|
throw new CustomException(ErrorCode.DATA_NO); |
|
|
|
|
} catch (IOException e){ |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
} finally { |
|
|
|
|
} finally { |
|
|
|
|
try { |
|
|
|
|
if(outputStream != null){ |
|
|
|
|
if (outputStream != null) { |
|
|
|
|
Objects.requireNonNull(outputStream).flush(); |
|
|
|
|
outputStream.close(); |
|
|
|
|
outputStream.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(inputStream != null){ |
|
|
|
|
if (inputStream != null) { |
|
|
|
|
inputStream.close(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|