Programing/JAVA

Java Spring FTP 파일 다운로드 FTP file download

리커니 2018. 2. 7.
반응형

 

Java Spring FTP 파일 다운로드 FTP file download

 

 

이전 포스팅들에서 파일을 선택하여 FTP 업로드 하는 방법에 대해 알아보았습니다.

해당 내용은 아래의 Link를 참고하세요.

 

Link : javascript spring 멀티파일선택 업로드 ajaxForm multipart/form-data MultipartHttpServletRequest

 

Link : JAVA 임시 파일 생성, FTP 파일 업로드

 

일반 다운로드는 아래의 Link를 참고하세요.

 

Link : 자바 파일 다운로드 소스, 한글인코딩, 브라우져 문제 해결

 

이제 이렇게 업로드 한 파일을 다운로드 하는 방법에 대해서 알아보도록 하겠습니다.

파일 다운로드는 업로드가 됐다는 가정하에, FTP 접속에 필요한 설정은 생략하고 진행하겠습니다.

설정은 위의 2번째 Link 참고.

 

파일에 대한 정보를 저장하는 테이블은 아래와 같습니다.

 

 

웹 페이지에서 FILE_ID 와 FILE_SEQ 를 받아 해당 파일의 정보를 가져온 후

그 정보로 FTP 경로상의 파일을 읽어오면 됩니다.

코드를 보도록 하죠.

 
 @RequestMapping(value="/ftpDownload.do", produces="text/plain;charset=UTF-8")
 public void ftpDownload(HttpServletRequest request, HttpServletResponse response){
     String fileId = request.getParameter("fileId");
     String fileSeq = request.getParameter("fileSeq");

     FileVO param = new FileVO();
     FileVO fileVO = new FileVO();
     boolean result = false;
     param.setFileId(fileId);
     param.setFileSeq(Integer.parseInt(fileSeq));
     try{
         fileVO = contentService.getFileInfo(param); 
     }catch(Exception e){
         e.printStackTrace();
     }

     try {
         setDisposition(fileVO.getFileNm(), request, response);
         FtpClient fc = new FtpClient(Define.FTP_SERVER_IP, Define.FTP_SERVER_PORT, Define.FTP_ID, Define.FTP_PW);
         result = fc.download(fileVO, response);
         if(!result){
            System.out.println("다운로드 에러!!!!!");
         }
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

 

3, 4 행에서 request parameter 로 fileId와 fileSeq를 받습니다.

그리고 받은 값으로 DB에서 세부정보를 가져옵니다. ( 13행 )

 

18 행의 setDisposition 함수에서는 브라우져 별 파일명의 한글 인코딩과 헤더 설정을 합니다.

19 행에서 FTP 클라이언트를 생성하고 20행에서 다운로드를 하는 것이죠.

setDisposition 과 그 내에서 사용되는 getBrowser 함수는 아래의 코드를 참고하세요.

 
 void setDisposition(String filename, HttpServletRequest request,HttpServletResponse response) throws Exception {
     String browser = getBrowser(request);
     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();
     } else {
         throw new IOException("Not supported browser");
     }

     response.setHeader("Content-Disposition", dispositionPrefix
     + encodedFilename);

     if ("Opera".equals(browser)) {
         response.setContentType("application/octet-stream;charset=UTF-8");
     }
 }

 

 private String getBrowser(HttpServletRequest request) {
      String header = request.getHeader("User-Agent");
      if (header.indexOf("MSIE") > -1) {
           return "MSIE";
      } else if (header.indexOf("Chrome") > -1) {
           return "Chrome";
      } else if (header.indexOf("Opera") > -1) {
           return "Opera";
      } else if (header.indexOf("Firefox") > -1) {
           return "Firefox";
      } else if (header.indexOf("Mozilla") > -1) {
           if (header.indexOf("Firefox") > -1) {
                return "Firefox";
           }else{
                return "MSIE";
           }
      }
      return "MSIE";
 }
 

 

이제 20행의 다운로드 함수를 보도록 하겠습니다.

파일에 대한 정보와 response 를 파라메터로 받습니다.

 
public class FtpClient {
    private String serverIp;
    private int serverPort;
    private String user;
    private String password;
    
    public FtpClient(String serverIp, int serverPort, String user, String password) {
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        this.user = user;
        this.password = password;
    } 
    public boolean download(FileVO param, HttpServletResponse response) throws SocketException, IOException, Exception {
        FileInputStream fis = null;
        FTPClient ftpClient = new FTPClient();
        
        try {
            ftpClient.connect(serverIp, serverPort);
            ftpClient.setControlEncoding("utf-8");
            int reply = ftpClient.getReplyCode();
            
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                throw new Exception(serverIp+" FTP 서버 연결 실패");
            }
            
            if(!ftpClient.login(user, password)) {
                ftpClient.logout();
                throw new Exception(serverIp+"FTP 서버에 로그인하지 못했습니다.");
            }
            
            ftpClient.setSoTimeout(1000 * 10);
            ftpClient.login(user, password);
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalActiveMode();
            
            String[] depth = param.getFilePath().split("/");
            String ftpPath = "/"+depth[2]+"/"+depth[3]+"/"+depth[4]+"/"+depth[5]+"/"+param.getSavedFileNm();
            boolean success  = false;
            OutputStream outputStream2 = new BufferedOutputStream(response.getOutputStream());
            InputStream inputStream = ftpClient.retrieveFileStream(ftpPath);
            byte[] bytesArray = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(bytesArray)) != -1) {
                outputStream2.write(bytesArray, 0, bytesRead);
            }

            success = ftpClient.completePendingCommand();
            outputStream2.close();
            inputStream.close();
            
            return success;
            
        } finally {
            if (ftpClient.isConnected()) {
                ftpClient.disconnect();
            }
            if (fis != null) {
                fis.close();
            }
        }
    }
}

 

앞부분에 대한 설명은 이전 포스팅을 참고해주시고

실질적으로 다운로드 구현부인 37 행부터 보도록 하겠습니다.

 
String[] depth = param.getFilePath().split("/");
String ftpPath = "/"+depth[2]+"/"+depth[3]+"/"+depth[4]+"/"+depth[5]+"/"+param.getSavedFileNm();
boolean success  = false;
OutputStream outputStream2 = new BufferedOutputStream(response.getOutputStream());
InputStream inputStream = ftpClient.retrieveFileStream(ftpPath);
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
    outputStream2.write(bytesArray, 0, bytesRead);
}

 

파일이 저장된 경로인 filePath를 받아 / 로 잘라 배열에 저장합니다.

불필요한 경로가 존재하기 때문에 잘라서 사용하는데,

굳이 이럴 필요 없이 파일이 있는 경로가 있다면 없어도 되는 코드 입니다.

 

ftpPath 변수에 실제 ftp상에 파일이 있는 경로와 파일명을 저장합니다.

response의 outputstream 으로 bufferoutputstream을 생성하고

InputStream inputStream = ftpClient.retrieveFileStream(ftpPath); 에서 ftp 경로상 파일을 inputstream으로 읽습니다.

읽은 inputstream을 바이트 배열로 읽어 outputstream으로 내보내는 것입니다.

 

4096 사이즈로 잘라서 읽는 이유는

파일의 용량이 클 경우나 네트워크 상태가 좋지 않을 경우 전체를 다 받아오지 못하는 경우가

존재하기 때문에 이를 방지하기 위함입니다.

 

파일의 경로에 해당 파일이 없거나, 명칭이 잘못된경우 0byte로 읽어오니,

FTP 상에 파일 경로 설정에 유의하세요.

반응형

댓글

💲 추천 글