package froala.editor; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import egovframework.com.cmm.util.EgovResourceCloseHelper; import egovframework.rte.fdl.cmmn.exception.EgovBizException; import froala.editor.file.FileOptions; import froala.editor.image.ImageOptions; import net.coobird.thumbnailator.Thumbnails; import net.coobird.thumbnailator.Thumbnails.Builder; /** * File functionality. * * @author florin@froala.com */ @Component public final class File { private static final Logger LOGGER = LoggerFactory.getLogger(File.class); /** * Content type string used in http multipart. */ public static final String multipartContentType = "multipart/form-data"; /** * Private constructor. */ private File() { } /** * File default options. */ public static final FileOptions defaultOptions = new FileOptions(); /** * Uploads a file to disk. * * @param req * Servlet HTTP request. * @param fileRoute * Route Server route where the file will be uploaded. This route * must be public to be accesed by the editor. * @return Object with link. * @throws EgovBizException */ public static EditorFileVO upload(HttpServletRequest req, String fileRoute) throws EgovBizException { return upload(req, fileRoute, defaultOptions); } /** * Uploads a file to disk. * * @param req * Servlet HTTP request. * @param fileRoute * Server route where the file will be uploaded. This route must * be public to be accesed by the editor. * @param options * File options. Defaults to {@link #defaultOptions} which has *
* Fieldname: "file"
* Validation: * * @return Object with link. * @throws EgovBizException */ public static EditorFileVO upload(HttpServletRequest req, String fileRoute, FileOptions options) throws EgovBizException { if (options == null) { options = defaultOptions; } if (req.getContentType() == null || req.getContentType().toLowerCase().indexOf(multipartContentType) == -1) { throw new EgovBizException("Invalid contentType. It must be " + multipartContentType); } MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)req; MultipartFile file = multipartHttpServletRequest.getFile(options.getFieldname()); // servlet 3.0 //Part filePart = req.getPart(options.getFieldname()); if (file == null) { throw new EgovBizException("Fieldname is not correct. It must be: " + options.getFieldname()); } // Generate random name. String file_extsn = FilenameUtils.getExtension(Utils.getFileName(file)).toLowerCase(); String extension = file_extsn; extension = (extension != null && extension != "") ? "." + extension : extension; String name; try { name = Utils.generateUniqueString() + extension; } catch (NoSuchAlgorithmException e) { // return null; throw new EgovBizException("NoSuchAlgorithmException!"); } String fullPath = fileRoute + name; InputStream fileContent; try { fileContent = file.getInputStream(); } catch (IOException e) { throw new EgovBizException("IOException!"); } String absoluteServerPath = getAbsoluteServerPath(req, fullPath); // String absoluteServerPath = linkName; java.io.File targetFile = null; if (absoluteServerPath != null && !absoluteServerPath.equals("")) { targetFile = new java.io.File(absoluteServerPath); } else { return null; } // Resize image. if (options instanceof ImageOptions && ((ImageOptions) options).getResizeOptions() != null) { ImageOptions.ResizeOptions imageOptions = ((ImageOptions) options).getResizeOptions(); Builder thumbnailsBuilder = Thumbnails.of(fileContent); // Check aspect ratio. int newWidth = imageOptions.getNewWidth(); int newHeight = imageOptions.getNewHeight(); if (imageOptions.getKeepAspectRatio()) { thumbnailsBuilder = thumbnailsBuilder.size(newWidth, newHeight); } else { thumbnailsBuilder = thumbnailsBuilder.forceSize(newWidth, newHeight); } try { thumbnailsBuilder.toFile(targetFile); } catch (IOException e) { LOGGER.error(e.getCause().getMessage()); } } else { try { FileUtils.copyInputStreamToFile(fileContent, targetFile); } catch (IOException e) { LOGGER.error(e.getCause().getMessage()); } } if (options.getValidation() != null && !options.getValidation().check(absoluteServerPath, file.getContentType())) { delete(req, fullPath); throw new EgovBizException("File does not meet the validation."); } // 정보 셋팅 EditorFileVO fileVO = new EditorFileVO(); fileVO.setLink(options.getDownloadUrl()); fileVO.setFullPath(fullPath); fileVO.setFileExtsn(file_extsn); fileVO.setOriginFileNm(file.getOriginalFilename()); fileVO.setSysFileNm(name); fileVO.setUploadDir(fileRoute); fileVO.setFileSize(file.getSize()); fileVO.setMime(file.getContentType()); return fileVO; } /** * Get absolute server path. * * @param req * Used to get the servlet context. * @param relativePath * Relative path. * @return Absolute path. */ public static String getAbsoluteServerPath(HttpServletRequest req, String relativePath) { // return req.getServletContext().getRealPath(relativePath); return relativePath; } /** * Delete a file from disk. * * @param req * Used to get the servlet context. * @param src * Server file path. */ public static void delete(HttpServletRequest req, String src) { String filePath = getAbsoluteServerPath(req, src); java.io.File file = new java.io.File(filePath); if (file.exists()) { file.delete(); } } /** * 압축파일(zip) 파일 업로드 - 압축해제 후 저장 * @param req * @param fileRoute * @param options * @return * @throws EgovBizException * @throws NoSuchAlgorithmException */ public static List zipUpload(HttpServletRequest req, String fileRoute, FileOptions options) throws EgovBizException, NoSuchAlgorithmException { if (options == null) { options = defaultOptions; } if (req.getContentType() == null || req.getContentType().toLowerCase().indexOf(multipartContentType) == -1) { throw new EgovBizException("Invalid contentType. It must be " + multipartContentType); } MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) req; MultipartFile file = multipartHttpServletRequest.getFile(options.getFieldname()); if (file == null) { throw new EgovBizException("Fieldname is not correct. It must be: " + options.getFieldname()); } List fileMap = new ArrayList<>(); ZipArchiveInputStream zin = null; ZipArchiveEntry entry = null; try { zin = new ZipArchiveInputStream(file.getInputStream(), "EUC-KR", false); java.io.File dir = new java.io.File(fileRoute); dir.setExecutable(true); dir.setReadable(true); dir.setWritable(true); if (!dir.exists()) { boolean result = false; try{ dir.mkdirs(); result = true; } catch(SecurityException se){ LOGGER.error("fail to process create Dir {}", se); } if(result) { LOGGER.info("Dir created"); } } try { while ((entry = zin.getNextZipEntry()) != null) { // Generate random name. String file_extsn = FilenameUtils.getExtension(entry.getName()); String extension = file_extsn; extension = (extension != null && extension != "") ? "." + extension : extension; String sysFileNm = Utils.generateUniqueString() + extension; String fullPath = fileRoute + sysFileNm; Path source = Paths.get(fullPath); OutputStream zout = null; try { zout = new FileOutputStream(source.toFile()); //버퍼 byte[] buf = new byte[1024]; int len; while ((len = zin.read(buf)) > 0) { zout.write(buf, 0, len); } // 정보 셋팅 EditorFileVO fileVO = new EditorFileVO(); fileVO.setLink(options.getDownloadUrl()); fileVO.setFullPath(fullPath); fileVO.setFileExtsn(file_extsn); fileVO.setOriginFileNm(entry.getName()); fileVO.setSysFileNm(sysFileNm); fileVO.setUploadDir(fileRoute); fileVO.setFileSize(entry.getSize()); fileVO.setMime(Files.probeContentType(source)); fileMap.add(fileVO); } catch (IOException e) { LOGGER.error("fail to process zipUpload File {}", e); } finally { EgovResourceCloseHelper.close(zout); } } } catch (IOException e) { LOGGER.error("fail to process zipUpload File {}", e); } finally { EgovResourceCloseHelper.close(zin); } } catch (IOException e) { LOGGER.error("fail to process zipUpload File {}", e); } return fileMap; } /** * 디렉토리 하위파일 및 디렉토리 삭제 * @param path */ public static void deleteDirFileFn(String path) { java.io.File file = new java.io.File(path); // 매개변수로 받은 경로를 파일객체선언 (/home/nation909/test 경로의 폴더를 지정함) java.io.File[] files = file.listFiles(); // 해당 폴더 안의 파일들을 files 변수에 담음 if(files.length > 0) { // 파일, 폴더가 1개라도 있을경우 실행 for (int i=0; i 0){ outStream.write(buffer, 0, length); } vo = new EditorFileVO(); vo.setLink(options.getDownloadUrl()); vo.setFullPath(copyFullPath); vo.setFileExtsn(tempFile.getFileExtsn()); vo.setOriginFileNm(tempFile.getOriginFileNm()); vo.setSysFileNm(tempFile.getSysFileNm()); vo.setUploadDir(copyPath); vo.setFileSize(tempFile.getFileSize()); vo.setMime(tempFile.getMime()); } catch(IOException e) { LOGGER.error("fail to process fileCopy {}", e); } finally { EgovResourceCloseHelper.close(inStream, outStream); } return vo; } /** * List 파일객체를 받아 다수의 파일을 압축파일로 압축 후 다운로드 * @param req * - HttpServletRequest * @param res * - HttpServletResponse * @param fileList * - 파일 정보를 담은 객체 * @param fileRoute * - 파일을 저장할 경로 * @throws EgovBizException */ public static void zipDown(HttpServletRequest req , HttpServletResponse res , List fileList , String fileRoute) throws EgovBizException { //추가 temp 경로 생성 String zipFilePath = Utils.getAddTempRoute(fileRoute); // 파일명 생성 시 날짜 Calendar cal = Calendar.getInstance(); //현재 년도, 월, 일 int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH) + 1; int date = cal.get(Calendar.DATE); String downloadFileName = year + "_" + month + "_" + date; String zipFileNm = downloadFileName + ".zip"; String fullPath = zipFilePath + zipFileNm; java.io.File file = new java.io.File(fullPath); try { //디렉토리 가져오기 java.io.File dir = new java.io.File(zipFilePath); dir.setExecutable(true); dir.setReadable(true); dir.setWritable(true); if (!dir.exists()) { boolean result = false; try{ dir.mkdirs(); result = true; } catch(SecurityException se){ LOGGER.error("fail to process create Dir {}", se); } if(result) { LOGGER.info("Dir created"); } } // ZipOutputStream을 FileOutputStream 으로 감쌈 FileOutputStream fout = null; ZipArchiveOutputStream zout = null; FileInputStream fin = null; try { fout = new FileOutputStream(file); zout = new ZipArchiveOutputStream(fout); for (EditorFileVO vo : fileList) { try { //본래 파일명 유지 ZipArchiveEntry zipEntry = new ZipArchiveEntry(vo.getOriginFileNm()); zout.putArchiveEntry(zipEntry); //경로포함 압축 //zout.putNextEntry(new ZipEntry(sourceFiles.get(i))); java.io.File voFile = new java.io.File(vo.getFullPath()); fin = new FileInputStream(voFile); byte[] buf = new byte[1024]; int len; // input file을 1024바이트로 읽음, zip stream에 읽은 바이트를 씀 while((len = fin.read(buf)) > 0) { zout.write(buf, 0, len); } } catch (IOException e) { LOGGER.error("fail to process zipDown file {}", e); // throw new Exception(e.getMessage()); } finally { EgovResourceCloseHelper.close(fin, zout); } } } catch (IOException e) { LOGGER.error("fail to process zipDown file {}", e); } finally { EgovResourceCloseHelper.close(zout); } String userAgent = req.getHeader("User-Agent"); String conVstr = null; if (userAgent.contains("MSIE")) { conVstr = URLEncoder.encode(zipFileNm,"UTF-8"); } else if (userAgent.contains("Trident")) { conVstr = URLEncoder.encode(zipFileNm,"UTF-8"); } else if(userAgent.contains("Chrome")) { conVstr = new String(zipFileNm.getBytes("UTF-8"), "ISO-8859-1"); } else if(userAgent.contains("Opera")) { conVstr = new String(zipFileNm.getBytes("UTF-8"), "ISO-8859-1"); } else if (userAgent.contains("Mozilla")){ conVstr = new String(zipFileNm.getBytes("UTF-8"), "ISO-8859-1"); } else { conVstr = new String(zipFileNm.getBytes("UTF-8"), "ISO-8859-1"); } res.setHeader("Content-Disposition", "attachment; fileName=\"" + conVstr + "\";"); res.setContentType("application/octet-stream;charset=UTF-8"); res.setHeader("Content-Transfer-Encoding", "binary"); FileInputStream fis = null; BufferedInputStream bis = null; ServletOutputStream so = null; BufferedOutputStream bos = null; try { fis = new FileInputStream(file); bis = new BufferedInputStream(fis); so = res.getOutputStream(); bos = new BufferedOutputStream(so); byte[] data = new byte[2048]; int input=0; while((input=bis.read(data))!=-1){ bos.write(data,0,input); bos.flush(); } } catch (IOException e) { LOGGER.error("fail to process zipDown file {}", e); } finally { EgovResourceCloseHelper.close(fis, bis, so, bos); } } catch (IOException e) { LOGGER.error("fail to process zipDown file {}", e); } finally { File.deleteDirFileFn(zipFilePath); } } }