Java上传文件到FTP中文名称处理

一、问题回顾
在上传文件到FTP服务器时,使用英文名都是能够正常上传文件的,但是文件名称带中文时会服务器会返回如下错误信息:

The filename, directory name, or volume label syntax is incorrect.
在这里插入图片描述

二、代码分析

经过调试发现,下面这句上传文件的代码返回的是false:

boolean storeFile = ftpClient.storeFile(String remote, InputStream local)
根据各种百度出来的解释是:FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码。

三、解决方法
首先需要设置FTP客户端编码为UTF-8

ftpClient.setControlEncoding(“UTF-8”);
其次,把remote以现在的编码,也就是GBK编码转成byte数字,然后把byte数组转成 iso-8859-1编码即可

remote = new String(remote.getBytes(“GBK”),“iso-8859-1”);
boolean storeFile = ftpClient.storeFile(remote, local)

在这里插入图片描述
这样就确实可以传上去,传上去的文件的名称也是对的,但是需要注意的是当你下载、获取文件信息时,你需要对文件名进行转码:

// 获取文件列表或者文件时自己反转一下文件名称编码,使之不乱码
FTPFile[] listFiles = ftpClient.listFiles(path);
for (FTPFile ftpFile : listFiles) {
    byte[] bytes = ftpFile.getName().getBytes("iso-8859-1");
    ftpFile.setName(new String(bytes, "GBK"));

}

// 获取文件列表或者文件时自己反转一下文件名称编码,使之不乱吗
byte[] bytes = path.getBytes("GBK");
InputStream fileStream = ftpClient.retrieveFileStream(new String(bytes, "iso-8859-1"));
log.info("文件 {} 下载成功!", path);

四、附代码
FTP相关工具类代码,主要如下:

/**
     * 获取FTP客户端链接带账号和端口
     *
     * @param ftpHost
     * @param ftpUserName
     * @param ftpPassword
     * @param ftpPort
     * @throws IOException
     */
    public static FTPClient getFTPClient(String ftpHost, int ftpPort, String ftpUserName,
                                         String ftpPassword) {
        FTPClient ftpClient = null;
        try {
            ftpClient = new FTPClient();
            ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
            ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                logger.error("未连接到FTP,用户名或密码错误");
                ftpClient.disconnect();
            } else {
                logger.info("FTP连接成功");
            }
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.enterLocalPassiveMode();
            //指定文件类型
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        } catch (SocketException e) {
            logger.error("FTP的IP地址可能错误");
        } catch (IOException e) {
            logger.error("FTP的端口错误");
        }
        return ftpClient;
    }



 /*
     * 上传文件到FTP服务器
     *
     * @param ftpHost FTP IP地址
     * @param ftpPort
     * @param fileUrl
     * @param fileName
     * @param dir
     */
    public static void upload(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword,
                                String fileUrl, String fileName, String dir) {
        //1、连接ftp服务器
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
        URL url;
        InputStream is = null;
        try {
            //2、获取文件
            url = new URL(fileUrl);
            HttpURLConnection urlcon;
            urlcon = (HttpURLConnection) url.openConnection();
            urlcon.setConnectTimeout(3000);
            urlcon.setReadTimeout(3000);
            urlcon.connect(); // 获取连接
            is = urlcon.getInputStream();
            //1)指定上传目录
            ftpClient.changeWorkingDirectory(dir);
            //2)指定文件类型
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //第一个参数:文件在远程服务器的名称
            //第二个参数:文件流
            boolean flag = ftpClient.storeFile(fileName, is);
            if (flag) {
                logger.info("上传成功");
            } else {
                logger.error("上传失败");
            }
        } catch (Exception e) {
            logger.error(" url:{} connection exception", fileUrl);
        } finally {
            try {
                ftpClient.logout();
            } catch (IOException e) {
                logger.error("关闭文件流异常");
            }
        }
    }


 /*
     * 从FTP服务器获取文件流
     *
     * @param ftpHost FTP IP地址
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP用户名密码
     * @param ftpPort FTP端口
     * @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
     * @param localPath 下载到本地的位置 格式:H:/download
     * @param fileName 文件名称
     */
    public static InputStream getFtpInputstream(String ftpHost, String ftpUserName,
                                                String ftpPassword, int ftpPort, String ftpPath,
                                                String fileName) {
        FTPClient ftpClient = null;
        InputStream in = null;
        try {
            ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
            ftpClient.changeWorkingDirectory(ftpPath);
            ftpClient.setBufferSize(200 * 1024 * 1024);
            in = ftpClient.retrieveFileStream(fileName);
            return in;
        } catch (FileNotFoundException e) {
            logger.error("没有找到" + ftpPath + "文件");
        } catch (SocketException e) {
            logger.error("连接FTP失败");
        } catch (IOException e) {
            logger.error("文件读取错误。");
        } finally {
            try {
                ftpClient.logout();
            } catch (IOException e) {
                logger.error("关闭文件流异常");
            }
        }
        return null;
    }
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值