linux中ftp中文名亂碼問題


問題觸發環境
1. java中使用org.apache.commons.net.ftp.FTPClient包
2. 通過chrome瀏覽器的file標簽上傳文件
3. 在windows上部署的FileZilla服務上傳的文件名正常顯示,在linux上的vsftpd服務文件名顯示亂碼
4. 直接chrome瀏覽器訪問linux的ftp目錄(chrome的默認編碼是UTF-8),正常顯示
5. 亂碼出現后,嘗試了各種方式編碼處理,造成了環境的各種不可追溯
解決過程
1. 查詢資料:FTP協議規定文件名編碼為iso-8859-1,所以上傳的文件目錄或文件名需要轉碼
2. 參考FileZilla的流程,會向FTP服務器發送OPTS UTF8 ON命令,開啟服務器對UTF-8的支持。
3. 仿照FileZilla的方式,可向服務器發送該指令,如果服務器支持UTF-8則使用UTF-8,否則使用本地編碼(GBK)處理中文名
4. 起作用的java關鍵代碼
private static String LOCAL_CHARSET = "GBK";

// FTP協議中規定的文件名編碼為: iso-8859-1
private static String FTP_CHARSET = "ISO-8859-1";

...
if (ftpClient.login(user, pwd)) {
    if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
        // 開啟服務器對UTF-8的支持,如果服務器支持就用UTF-8,否則使用本地編碼(GBK)
        LOCAL_CHARSET = "UTF-8";
    }
    ftpClient.setControlEncoding(LOCAL_CHARSET);
    // 設置被動模式
    ftpClient.setLocalPassiveMode();
    ...
}

ftpClient.changeWorkingDirectory(encodingServerPath(remotePath))

// 上傳的時候使用
ftpClient.storeFile(encodingServerPath(fileName), inputStream);

/**
 * 編碼文件路徑
 */
private static String encodingServerPath(String path) throws UnsupportedEncodingException {
    // FTP協議里面,規定文件名編碼為iso-8859-1,所以目錄名或文件名需要轉碼,replace處理文件路徑
    return new String(path.replace("\\", "/").replaceAll("//", "/").getBytes(LOCAL_CHARSET), FTP_CHARSET);
}

// 下載的時候使用
ftpClient.retrieveFile(encodingServerPath(fileName), outputStream);

// 打印ftp工作目錄時需要切換轉碼
System.out.println("當前工作目錄:"+ new String(ftp.printWorkingDirectory().getBytes(FTP_CHARSET), LOCAL_CHARSET));
個人理解的轉碼和解碼過程如下:
filePath 的原始編碼: origin_charset => start
java后台: new String(filePath.getBytes(Local_CHARSET), "ISO-8859-1") => step_1
FTP Protocol: new String(filePath.getBytes("ISO-8859-1"), FTP_CHARSET) => step_2
FTP 服務器的默認編碼: new String(filePath.getBytes(FTP_CHARSET), server_charset) => end
if(Local_CHARSET == FTP_CHARSET) upload正常, else upload異常(無法創建和切換目錄)
if(origin_charset == server_charset) 文件名在FTP服務器上顯示正常, else 文件在FTP服務器顯示亂碼,download異常
如果filePath的編碼與上傳時的編碼不一致,download異常
web項目開發中出現亂碼,要從傳值開始分析編碼,逐步排查,確保編碼一致。要注意瀏覽器和某些方法的默認行為(場景較多,需要時查詢即可,不在此處羅列)

測試后的代碼托管在GitHub中,地址https://github.com/Hlingoes/file-message-server,位於application/FtpService中,供參考和提出改進建議


免責聲明!

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



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