解决:获取FTP服务器上带有中文路径的文件乱码问题导致找不到文件或者切换路径异常的问题

如果没有没有中文路径,则获取文件或者获取文件流都是比较简单的。网上有大把的例子,拿来改薄该博就可以了。但一出现中文路径,则难度增加不少。关键是要知道你公司的ftp服务器默认的编码格式。这个很重要!

一般默认ftp服务器是GBK编码格式的。好,先认识一下几个常见的编码,今天都要用。
1. GBK 2. ISO-8859-1 3. UTF-8
我们一般登录到FTP服务器上时,所在的目录就是根目录,当然,如果不是也没太大关系,只要知道根目录到指定要进入的目录路径就能切到指定目录上。比如:String path="/records/sxks/凯森022/20171001/2023249/2023249-01.mp3"; 这是我们要找的录音文件全路径。但是我们等进来进的目录不知道是那层,这都无所谓,直接用这个路径就能找到我们的文件。但是这里问题就在路径有中文,如何让路径编码正确?这里可以通过用方法:ftpClient.changeWorkingDirectory(path)来看返回的boolean值判断切换目录成功没有来确认。true表示成功。

1.拆分路径

/records/sxks/凯森022//20171001/2023249/2023249-01.mp3,只要第一个路径切换成功,表示编码方式对,就可以找到全路径下的文件了。(当然还有别的拆分方式/records/sxks/凯森022/20171001/2023249/+2023249-01.mp3 等等)

2.对路径进行编码处理后测试切换。

由于老路径String oldPath="/records/sxks/凯森022/";

2.1 对路径进行GBK->ISO编码,用上面的方法尝试。我就是用这种方式才能正常切换到中文目录下的。

String newPath1=new String(oldPath.getBytes("GBK"),"ISO-8859-1");
boolean flag=ftpClient.changeWorkingDirectory(newPaths);

2.2 对路径进行GBK->UTF-8编码,用上面的方法尝试。我就是用这种方式才能正常切换到中文目录下的。

String newPath1=new String(oldPath.getBytes("GBK"),"UTF-8");
boolean flag=ftpClient.changeWorkingDirectory(newPaths);

2.3 还可以通过下面的方法判断ftp服务器是不是支持UTF-8这种编码方式

private String LOCAL_CHARSET="GBK";
if(FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF-8","ON"))){
    LOCAL_CHARSET="UTF-8";
}
  1. 具体代码如下
package com.zhanglf.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import com.zhanglf.dto.entity.FTPConfigBo;

import lombok.extern.slf4j.Slf4j;


@Slf4j
public class FTPUtil { 
    public static String LOCAL_CHARSET="GBK";
    public static String DEFAULT_CHARSET="iso-8859-1";

    /** * 获取FTPClient对象 * @param host FTP对应的IP地址 * @param port FTP端口 * @param username FTP用户名 * @param password FTP用户密码 * @return */
    public static FTPClient getFTPClient(FTPConfigBo ftpConfig){
        FTPClient ftpClient=new FTPClient();
        try {
            ftpClient=new FTPClient();
            //如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
            //ftpClient.connect(host, port);
            ftpClient.connect(ftpConfig.getHost());
            if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
                if(ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword())){
                    log.info("FTP连接成功!");
                    ftpClient.setControlEncoding(LOCAL_CHARSET);//中文支持
                    ftpClient.enterLocalPassiveMode();//设置被动模式
                    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);//设置传输模式
                    //开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                    if(FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF-8","ON"))){
                        LOCAL_CHARSET="UTF-8";
                    }
                }
            }else{
                log.info("未连接到FTP,用户名或者密码错误。");
                ftpClient.disconnect();
            }
        } catch (Exception e) {
            log.error("FTP获取ftp客户端对象异常,异常信息为: "+e.getMessage(),e);
        }

        return ftpClient;
    }

    public static byte[] input2byte(InputStream in) throws IOException{
        ByteArrayOutputStream swapStream =new ByteArrayOutputStream();
        byte[] buff=new byte[in.available()];
        int rc=0;
        while((rc = in.read(buff,0,100)) > 0){
            swapStream.write(buff,0,rc);
        }
        byte[]  in2b=swapStream.toByteArray();
        swapStream.close();
        return in2b;
    }

    /** * 根据ftp文件路径和ftp连接获取该文件对应的流信息 * @param path 文件在ftp的路径,比如:/records/sxks/ /凯森1W4/20171211/20367962/ + 20367962-01.mp3 * @param ftpClient * @return * @throws Exception */
    public static InputStream getInputStreamFromFtp(String pathName,FTPClient ftpClient) throws Exception{
        String[] pathArray = pathName.split("/");
        String filename=pathArray[pathArray.length-1];  //获取录音文件名:20300981-01.mp3
        String contno=pathArray[pathArray.length-2];    //获取保单号:20300981
        String ymd=pathArray[pathArray.length-3];       //获取年月日:20171211
        String code=pathArray[pathArray.length-4];      //获取外包机构码:凯森1W4
        String wbcode=pathArray[pathArray.length-5];    //获取外包商登录名:shzh,sxks等等
        String dic=code+"/"+ymd+"/"+contno+"/";
        //防止中文编码导致目录找不到
        String directory  = new String(dic.getBytes(FTPUtil.LOCAL_CHARSET),FTPUtil.DEFAULT_CHARSET);
        //更换目录到当前目录
        ftpClient.changeWorkingDirectory(directory);
        ftpClient.setBufferSize(1024);
        return ftpClient.retrieveFileStream(filename);
    }

}
    原文作者:万米高空
    原文地址: https://blog.csdn.net/zhanglf02/article/details/78932525
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞