package synap.editor.server.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
@Controller
public class WmfToPngController {
static String IMAGE_UPLOAD_DIR_REL_PATH = "uploads" + File.separator + "image";
static String OUTPUT_DIR_REL_PATH = "uploads" + File.separator + "output";
@PostMapping(value = "/wmfToPng", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public ResponseEntity<Map<String, String>> convertWmfToPng(HttpServletRequest request, @RequestParam("file") MultipartFile wmfImageFile) /**
* 업로드된 WMF 이미지를 PNG로 변환한 후, 변환된 이미지의 다운로드 URL을 반환합니다.
*
* @param request throws IOException { 클라이언트의 HTTP 요청 객체
String ROOT_ABS_PATH = request.getSession().getServletContext().getRealPath("");
* @param wmfImageFile 변환할 WMF 이미지 String UPLOAD_DIR_ABS_PATH = ROOT_ABS_PATH + File.separator + IMAGE_UPLOAD_DIR_REL_PATH;파일
* @return makeDirectory(UPLOAD_DIR_ABS_PATH); 변환된 PNG 파일의 String다운로드 fileNameURL을 = wmfImageFile.getOriginalFilename();
포함한 JSON 응답
* @throws StringIOException inputFileAbsPath = UPLOAD_DIR_ABS_PATH + File.separator파일 +저장 fileName;또는 변환 중 예외 발생 시
writeFile(inputFileAbsPath, wmfImageFile.getBytes()); */
@PostMapping(value = "/wmfToPng", consumes // 변환을 위한 작업 디렉토리 생성= MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public ResponseEntity<Map<String, String>> convertWmfToPng(HttpServletRequest Calendar cal = Calendar.getInstance();request, @RequestParam("file") MultipartFile wmfImageFile)
String yearMonth = String.format("%04d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1); throws IOException {
String uuidROOT_ABS_PATH = UUID.randomUUIDrequest.getSession().getServletContext().toStringgetRealPath("");
String worksDirAbsPathUPLOAD_DIR_ABS_PATH = ROOT_ABS_PATH + OUTPUT_File.separator + IMAGE_UPLOAD_DIR_REL_PATH + File.separator + yearMonth + File.separator + uuid;
makeDirectory(worksDirAbsPathUPLOAD_DIR_ABS_PATH);
String // 이미지 변환fileName = wmfImageFile.getOriginalFilename();
String executeConverter(inputFileAbsPath, worksDirAbsPath = UPLOAD_DIR_ABS_PATH + File.separator + "output.png")fileName;
// 변환이 끝난 원본업로드된 파일 삭제저장
deleteFilewriteFile(inputFileAbsPath, wmfImageFile.getBytes());
// 변환된변환을 파일에위한 접근할작업 경로디렉토리 설정생성
StringCalendar downloadUrlcal = requestCalendar.getSchemegetInstance() + "://" + request.getServerName() + ":" + request.getServerPort()
;
String yearMonth = String.format("%04d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
String uuid + "/download?fileName=" + uuid + "/output.png";
Map<String, String> response = new HashMap<>(= UUID.randomUUID().toString();
String worksDirAbsPath = ROOT_ABS_PATH + OUTPUT_DIR_REL_PATH + File.separator + yearMonth + File.separator + uuid;
makeDirectory(worksDirAbsPath);
response.put("uploadPath", downloadUrl);
// 이미지 변환
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON executeConverter(inputFileAbsPath, worksDirAbsPath + File.separator + "output.png");
return// ResponseEntity변환이 끝난 원본 파일 삭제
.status(HttpStatus.OK)deleteFile(inputFileAbsPath);
// 다운로드 URL 생성 - 변환된 파일을 .headers(headers)사용하는 예시입니다.
String downloadUrl = .body(response);
}request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ @GetMapping("/download?fileName=") + uuid + public void downloadFile(@RequestParam String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {"/output.png";
Map<String, String> response = new HashMap<>();
String ROOT_ABS_PATH = request.getSession().getServletContext().getRealPath(""response.put("uploadPath", downloadUrl);
Calendar HttpHeaders calheaders = Calendar.getInstancenew HttpHeaders();
String yearMonth = String.format("%04d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);headers.setContentType(MediaType.APPLICATION_JSON);
return ResponseEntity
String downloadDirPath = ROOT_ABS_PATH + OUTPUT_DIR_REL_PATH + File.separator + yearMonth + File.separator; .status(HttpStatus.OK)
File file = new File(downloadDirPath + File.separator + fileName); .headers(headers)
if (!file.exists()) { response.setStatus(HttpServletResponse.SC_NOT_FOUND.body(response);
}
/**
return; * 변환된 PNG 파일을 클라이언트가 }다운로드할 수 있도록 스트리밍합니다.
response.setContentType("application/octet-stream");*
*
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\""); * @param fileName 다운로드할 response.setContentLengthLong(file.length());
파일의 상대 경로
* @param request try (InputStream is = new FileInputStream(file); HTTP 요청 객체
* @param OutputStreamresponse os = response.getOutputStream()) { HTTP 응답 객체
byte[]* buffer@throws =IOException new byte[8192]; 파일이 존재하지 않거나 스트리밍 중 오류 발생 시
int bytesRead; */
@GetMapping("/download")
public whilevoid downloadFile((bytesRead@RequestParam = is.read(buffer)) != -1) {
String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
String ROOT_ABS_PATH os.write(buffer, 0, bytesRead= request.getSession().getServletContext().getRealPath("");
Calendar cal = Calendar.getInstance();
} String }yearMonth = String.format("%04d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + }1);
/** String downloadDirPath = * 이미지 변환 모듈을 실행합니다.
*/ROOT_ABS_PATH + OUTPUT_DIR_REL_PATH + File.separator + yearMonth + File.separator;
public static int executeConverter(String inputFilePath, String outputFilePath) {
File file = new File(downloadDirPath + File.separator + fileName);
String SEDOC_CONVERTER_DIR_ABS_PATH = "변환모듈이 존재하는 디렉토리의 절대경로";if (!file.exists()) {
String TEMP_DIR_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "temp"; response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
//String SEDOC_CONVERTER_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "sedocConverter_exe"; }
String SEDOC_CONVERTER_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "sedocConverter.exe";// window server용 // 파일 다운로드 처리
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; makeDirectory(TEMP_DIR_ABS_PATH);
filename=\"" + file.getName() + "\"");
response.setContentLengthLong(file.length());
try (InputStream is = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
}
/**
* 외부 이미지 변환 도구(sedocConverter)를 호출하여 WMF 파일을 PNG로 변환합니다.
*
* @param inputFilePath 변환할 WMF 파일의 절대 경로
* @param outputFilePath 결과 PNG 파일의 저장 경로
* @return 프로세스 종료 코드 (0: 성공, 그 외: 실패)
*/
public static int executeConverter(String inputFilePath, String outputFilePath) {
String SEDOC_CONVERTER_DIR_ABS_PATH = "변환모듈이 존재하는 디렉토리의 절대경로";
String TEMP_DIR_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "temp";
String SEDOC_CONVERTER_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "sedocConverter_exe";
// String SEDOC_CONVERTER_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "sedocConverter.exe";// window server용
makeDirectory(TEMP_DIR_ABS_PATH);
// 변환 명령 구성
String[] cmd = {SEDOC_CONVERTER_ABS_PATH, inputFilePath, outputFilePath, TEMP_DIR_ABS_PATH};
try {
Timer t = new Timer();
Process proc = Runtime.getRuntime().exec(cmd);
TimerTask killer = new TimeoutProcessKiller(proc);
t.schedule(killer, 20000);
int exitValue = proc.waitFor();
killer.cancel();
return exitValue;
} catch (Exception e) {
// 변환 명령 구성 e.printStackTrace();
String[] cmd = {SEDOC_CONVERTER_ABS_PATH, inputFilePath, outputFilePath, TEMP_DIR_ABS_PATH}return -1;
try}
{ }
/**
Timer t = new Timer();
* 파일 경로로부터 바이트 배열을 읽어 반환합니다.
*
Process proc = Runtime.getRuntime().exec(cmd);
* @param filePath 읽을 파일의 경로
TimerTask killer = new TimeoutProcessKiller(proc);* @return t.schedule(killer, 20000); 파일 내용의 바이트 배열
* int@throws exitValueIOException = proc.waitFor(); 파일 읽기 중 예외 발생 시
killer.cancel();
*/
private static byte[] readFileToByteArray(String filePath) throws IOException {
return exitValue; File file }= catchnew File(Exception efilePath);
{ try (FileInputStream fis = new e.printStackTraceFileInputStream(file);) {
return -1fis.readAllBytes();
}
}
/**
* 파일을지정한 읽어서경로에 바이트 배열로배열을 파일로 반환합니다저장합니다.
*/
private static* byte[] readFileToByteArray(String filePath) throws IOException {
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file)) {
@param path 저장할 경로
* @param bytes return fis.readAllBytes(); }저장할 데이터
} * @throws IOException /** 파일 쓰기 중 *예외 파일을발생 씁니다.시
*/
private static void writeFile(String path, byte[] bytes) throws IOException {
try (OutputStream os = new FileOutputStream(path)) {
os.write(bytes);
}
}
/**
* 지정한 경로의 파일을 삭제합니다..
*
* @param path 삭제할 파일 경로
*/
private static void deleteFile(String path) {
File file = new File(path);
if (file.exists()) {
file.delete();
}
}
/**
* 지정한 경로의 디렉토리가 없는존재하지 경우않으면 디렉토리를 생성합니다.
*
* @param dirPath 생성할 디렉토리 경로
*/
private static void makeDirectory(String dirPath) {
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
}
/**
* 주어진 프로세스를 일정 시간 후 강제 종료하는 TimerTask
*/
private static class TimeoutProcessKiller extends TimerTask {
private Process p;
public TimeoutProcessKiller(Process p) {
this.p = p;
}
@Override
public void run() {
p.destroy();
}
}
} |