package com.oqpo.api.service; import com.oqpo.api.constant.ApiConstants; import com.oqpo.api.entity.oper.FileEntity; import com.oqpo.api.enums.SystemMessageCode; import com.oqpo.api.exception.GlobalException; import com.oqpo.api.mapper.FileMapper; import com.oqpo.api.model.FileModel; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.text.DecimalFormat; import java.util.List; import java.util.UUID; @Slf4j @Service public class FileService extends CommonService { @Autowired private FileMapper fileMapper; @Value("${ftp.path}") String ftpPath; @Value("${ftp.host}") String ftpHost; @Value("${ftp.port}") Integer ftpPort; @Value("${ftp.user}") String ftpUser; @Value("${ftp.pass}") String ftpPass; @Value("${ftp.domain}") String ftpDomain; @Value("${file.domain.url}") String domainUrl; @Value("${file.upload.path}") String uploadPath; @Value("${file.upload.folder}") String uploadFolder; public FileEntity fileUpload(String userId, String fileNo, String path, MultipartFile multipartFile) throws Exception { FileModel fileModel = new FileModel(); FTPClient client = new FTPClient(); try { if ((ApiConstants.FILE_MAX * (1024*1024*100)) < multipartFile.getSize()) { throw new GlobalException(SystemMessageCode.FILE_CAPACITY_FAIL); } client.setControlEncoding("UTF-8"); client.connect(ftpHost, ftpPort); int resultCode = client.getReplyCode(); if (!FTPReply.isPositiveCompletion(resultCode)) { System.out.println("FTP server refused connection.!"); return null; } else { client.setSoTimeout(1000); if (!client.login(ftpUser, ftpPass)) { System.out.println("Login Error!"); return null; } } String orgFileName = multipartFile.getOriginalFilename(); String extension = FilenameUtils.getExtension(orgFileName); String fileName = UUID.randomUUID().toString() + "." + extension; String savePath = uploadPath + "/" + fileName; String remotePath = ftpPath + uploadFolder + "/" + path + "/" + fileName; String downUrl = ftpDomain + uploadFolder + "/" + path + "/" + fileName; File file = new File(savePath); file.getParentFile().mkdirs(); multipartFile.transferTo(file); FileInputStream inputStream = new FileInputStream(file); client.enterLocalPassiveMode(); client.makeDirectory(ftpPath + uploadFolder + "/" + path); client.setFileType(FTP.BINARY_FILE_TYPE); client.storeFile(remotePath, inputStream); inputStream.close(); deleteFolder(uploadPath); fileModel.setFileNo(fileNo); fileModel.setFileName(fileName); fileModel.setFileOrgName(orgFileName); fileModel.setDomainUrl(downUrl); fileModel.setFilePath(path); fileModel.setExtension(extension); fileModel.setFileSize(byteCalculation(multipartFile.getSize())); return saveFile(userId, fileModel); } catch (GlobalException e) { throw new GlobalException(e.getSystemMessageCode()); } catch (Exception e) { e.printStackTrace(); throw new GlobalException(SystemMessageCode.FILE_ERR); } finally { try { if (client.isConnected()) { client.logout(); client.disconnect(); } } catch (Throwable e) { e.printStackTrace(); } } } public FileEntity saveFile(String userId, FileModel fileModel) { String fileNo = fileModel.getFileNo(); if (fileNo.trim().equals("")) { fileNo = this.fnGetKeyNo(1); } String filePath = domainUrl + uploadFolder + "/" + fileModel.getFilePath() + "/" + fileModel.getFileName(); FileEntity fileEntity = new FileEntity(); fileEntity.setFileNo(fileNo); fileEntity.setFileOrgNm(fileModel.getFileOrgName()); fileEntity.setFileNm(fileModel.getFileName()); fileEntity.setFilePath(filePath); fileEntity.setFileType(fileModel.getFilePath()); fileEntity.setFileSize(fileModel.getFileSize()); fileEntity.setAddId(userId); fileMapper.insertFile(fileEntity); return fileEntity; } public List fileList(String fileNo) throws Exception { return fileMapper.selectFileList(fileNo); } public void fileDelete(String fileNo, Integer fileSeq) { fileMapper.deleteFile(fileNo, fileSeq); } public void fileDownload(String fileNo, Integer fileSeq, HttpServletRequest request, HttpServletResponse response) throws Exception { FileModel fileModel = new FileModel(); FTPClient client = new FTPClient(); try { FileEntity entity = fileMapper.selectFile(fileNo, fileSeq); if (entity == null) { throw new GlobalException(SystemMessageCode.FILE_DOWN_ERR); } String filePath = ftpPath + uploadFolder + "/" + entity.getFileType() + "/"; String fileName = entity.getFileNm(); client.setControlEncoding("UTF-8"); client.connect(ftpHost, ftpPort); int resultCode = client.getReplyCode(); if (!FTPReply.isPositiveCompletion(resultCode)) { System.out.println("FTP server refused connection.!"); } else { client.setSoTimeout(1000); if (!client.login(ftpUser, ftpPass)) { System.out.println("Login Error!"); } } File file = new File(uploadPath); file.mkdirs(); FileOutputStream fo = new FileOutputStream(uploadPath + fileName); client.enterLocalPassiveMode(); client.setFileType(FTP.BINARY_FILE_TYPE); if (client.retrieveFile(filePath + fileName, fo)) { System.out.println("Download - Success"); } fo.close(); fileModel.setFilePath(uploadPath + fileName); File attachFile = new File(fileModel.getFilePath()); if (attachFile.exists() && attachFile.isFile()) { response.setContentType("application/octet-stream; charset=utf-8"); response.setContentLength((int) attachFile.length()); String browser = getBrowser(request); String disposition = getDisposition(entity.getFileOrgNm(), browser); response.setHeader("Content-Disposition", disposition); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null; fis = new FileInputStream(attachFile); FileCopyUtils.copy(fis, out); if (fis != null) fis.close(); out.flush(); out.close(); } else { throw new GlobalException(SystemMessageCode.FILE_DOWN_ERR); } } catch (Exception e) { e.printStackTrace(); throw new GlobalException(SystemMessageCode.FILE_DOWN_ERR); } finally { try { deleteFolder(uploadPath); if (client.isConnected()) { client.logout(); client.disconnect(); } } catch (Throwable e) { e.printStackTrace(); } } } public void deleteFolder(String delPath) { File folder = new File(delPath); File[] folderList = folder.listFiles(); for (int i = 0; i < folderList.length; i++) { if (folderList[i].isFile()) { folderList[i].delete(); } else { deleteFolder(folderList[i].getPath()); } folderList[i].delete(); } folder.delete(); } public String byteCalculation(Long bytes) { String retFormat = "0"; String[] s = { "bytes", "KB", "MB", "GB", "TB", "PB" }; if (bytes != 0) { int idx = (int) Math.floor(Math.log(bytes) / Math.log(1024)); DecimalFormat df = new DecimalFormat("#,###.##"); double ret = ((bytes / Math.pow(1024, Math.floor(idx)))); retFormat = df.format(ret) + " " + s[idx]; } else { retFormat += " " + s[0]; } return retFormat; } public String getBrowser(HttpServletRequest request) { String header = request.getHeader("User-Agent"); if (header.indexOf("MSIE") > -1 || header.indexOf("Trident") > -1) return "MSIE"; else if (header.indexOf("Chrome") > -1) return "Chrome"; else if (header.indexOf("Opera") > -1) return "Opera"; return "Firefox"; } public String getDisposition(String filename, String browser) throws UnsupportedEncodingException { String dispositionPrefix = "attachment;filename="; String encodedFilename = null; if (browser.equals("MSIE")) { encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20"); } else if (browser.equals("Firefox")) { encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\""; } else if (browser.equals("Opera")) { encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\""; } else if (browser.equals("Chrome")) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < filename.length(); i++) { char c = filename.charAt(i); if (c > '~') { sb.append(URLEncoder.encode("" + c, "UTF-8")); } else { sb.append(c); } } encodedFilename = sb.toString(); } return dispositionPrefix + encodedFilename; } }