Java FTP下載文件以及編碼問題小結


問題

之前在開發過程中,遇到了一點問題,我要訪問一個FTP服務器去下載文件詳細情況如下:

1. 需要傳入一個可能為中文的文件名;

2. 通過文件名去FTP上尋找該文件;

3. FTP服務器的命名編碼為“GBK”;

思路

1.通過GET方法直接將文件名負載URL后面,但需要通過轉碼;

2.在Java Controller中收到參數后,進行解碼,解碼為正常數據;

3.用正常數據再轉碼為GBK,到Service中去調用FTP即可

4.(因公司安全考慮,我們需要在另一個模塊中調用FTP)通過rest接口將文件名傳出,另一模塊獲取到文件流轉換為byte[]傳回,調用response輸出即可

總結

編碼問題的解決方案:

 

Jquery對URL以及參數轉碼,據我所了解的主要應用encodeURI、encodeURIComponent,例如我需要傳入變量名為fileDepence

var downloadDepence=fileID+"-"+filename;
window.location.href=encodeURI(ajaxurl+"/coadownload/downloadFile?fileDepence="+encodeURIComponent(downloadDepence));

這樣我在后台就可以接收到轉碼過后的fileDepence這個串,通過驗證encodeURIComponent會以“utf-8”進行轉碼,所以我們使用Java對其解碼:

String viewItem=java.net.URLDecoder.decode(fileDepence, "utf-8");

這樣得到的viewItem就與我們原本要傳入的值一致了,如果傳入的為中文文件名,則此時viewItem便是對應的中文文件名了。

之后我又了解一下,通過JS來完成GBK的轉碼比較麻煩,而采用Unicode的Java則比較方法,則同理,我們使用viewItem在以GBK來轉一次碼,就可以得到對應的FTP服務器中的文件名了。

 String GBKItem= URLEncoder.encode(viewItem,"GBK");

FTP的解決方法

 

建立一個FTP連接的公用類

public static FtpClient connectFTP(String url, int port, String username, String password) {
        //創建ftp
        FtpClient ftp = null;
        try {
            //創建地址
            SocketAddress addr = new InetSocketAddress(url, port);
            //連接
            ftp = FtpClient.create();
            ftp.connect(addr);
            //登陸
            ftp.login(username, password.toCharArray());
            ftp.setBinaryType();
        } catch (FtpProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.info("已登錄到FTP服務器!" + new Date());
        return ftp;
    }

在另一個模塊的Service中建立一個下載的方法,在rest接口訪問的Controller中調用該方法。

 public FileBtye downloadfilefromFTP(String fileDepence,HttpServletResponse response) throws IOException, FtpProtocolException {
        FileBtye file=new FileBtye();                      //FileBtye為一個只包含btye[]的對象,主要用於適合Controller的responsebody的json傳出
        response.setCharacterEncoding("utf-8");     
        fileDepence=fileDepence.replace("\"", "");        //rest接口傳輸過來的值需要做一定的格式化處理
        FtpClient ftpClient= FTPManager.connectFTP(FTPHost, Integer.parseInt(FTPPort), FTPUserName, FTPPassWord);   //通過properties文件讀取
        InputStream is = null;
        ftpClient.changeDirectory("//filepath");        //文件目錄
        is = ftpClient.getFileStream(fileDepence);     //獲取文件流
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];                //buff用於存放循環讀取的臨時數據
        int rc = 0;
        while ((rc = is.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] fileByte = swapStream.toByteArray();
        file.setFileinfo(fileByte);
        is.close();
        return file;
    }

在本地Service中調用rest接口完成輸出response輸出即可,同時要注意response的設置

       String viewItem=java.net.URLDecoder.decode(fileDepence, "utf-8");
            //FTP服務器命名規則以GBK編碼
            String GBKItem= URLEncoder.encode(viewItem,"GBK");
       //調用rest接口,拿到返回的FileBtye FileBtye downloadStream
=restTemplate.postForObject(gatewayRootUrl + GatewayUrlConstant.COA_DOWNLOAD + GatewayUrlConstant.DOWNLOAD_FILE, GBKItem, FileBtye.class); if(downloadStream!=null){ //設置信息頭 response.setCharacterEncoding("utf-8"); //設置編碼 response.setContentType("multipart/form-data"); //根據文件確定文件格式 response.setHeader("Content-Disposition", "attachment;fileName=" + viewItem); //設置文件名 ServletOutputStream out; //輸出流輸出 out = response.getOutputStream(); out.write(downloadStream.getFileinfo()); out.flush(); out.close(); logger.info("下載文件成功" + new Date()); }else { logger.info("下載文件不存在" + new Date()); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM