FTPClient上传文件大小为0字节但不报错的问题顺利解决

今天通过FTPClient上传文件时出现,虽然无错误出现但是上传到服务器端的文件大小为0。

如图:

 

 之前的代码:

//FTP文件上传
    public static boolean upload(String hostname, int port, String username, String password,
                                 String targetPath, String fileName, InputStream inputStream) throws SocketException, IOException {
        //实例化ftpClient
        FTPClient ftpClient = new FTPClient();

        //设置登陆超时时间,默认是20s
        ftpClient.setDataTimeout(12000);
        //1.连接服务器
        ftpClient.connect(hostname, port);
        
        //2.登录(指定用户名和密码)
        boolean b = ftpClient.login(username, password);
        if (!b) {
            log.info("ftp登陸超時");
            if (ftpClient.isConnected()) {
                // 断开连接
                ftpClient.disconnect();
            }
        }
        log.info("ftp登陸成功");
        // 设置字符编码
        ftpClient.setControlEncoding("UTF-8");
        //基本路径,一定存在
        String[] pathArray = targetPath.split("/");
        for (String path : pathArray) {
            if (path.equals("")) {
                continue;
            }
            //3.指定目录 返回布尔类型 true表示该目录存在
            boolean dirExsists = ftpClient.changeWorkingDirectory(path);
            //4.如果指定的目录不存在,则创建目录
            if (!dirExsists) {
                //此方式,每次,只能创建一级目录
                boolean flag = ftpClient.makeDirectory(path);
                if (!flag) {
                    System.out.println("文件目录创建失败!");
                    return false;
                }
                ftpClient.changeWorkingDirectory(path);
            }
        }
        log.info("重新指定上传文件的路径:" + targetPath);
        //重新指定上传文件的路径
//        ftpClient.changeWorkingDirectory(targetPath);
        //5.设置上传文件的方式
        ftpClient.setBufferSize(1024 * 1024 * 10);
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.enterLocalPassiveMode();
        /**
         * 6.执行上传
         * remote 上传服务后,文件的名称
         * local 文件输入流
         * 上传文件时,如果已经存在同名文件,会被覆盖
         */
        boolean uploadFlag = false;
        try {
            uploadFlag = ftpClient.storeFile(fileName, inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ftpClient.logout();
            ftpClient.disconnect();
        }
        if (uploadFlag) {
            System.out.println("上传成功!");
            return true;
        }
        return false;
    }

打上断点debug,当运行到 

uploadFlag = ftpClient.storeFile(fileName, inputStream);

就卡着不到,也不报错。

百度到很多都说要设置为被动模式,要加:

ftpClient.enterLocalPassiveMode();

但是我明明已经加了还是不行。

于是各种找方法,终于知道问题在哪里了,原来 ftpClient.enterLocalPassiveMode();加的地方不对,要加在建立连接和登录之间才可以。

现在的代码:

//FTP文件上传
    public static boolean upload(String hostname, int port, String username, String password,
                                 String targetPath, String fileName, InputStream inputStream) throws SocketException, IOException {
        //实例化ftpClient
        FTPClient ftpClient = new FTPClient();

        //设置登陆超时时间,默认是20s
        ftpClient.setDataTimeout(12000);
        //1.连接服务器
        ftpClient.connect(hostname, port);
        ftpClient.enterLocalPassiveMode();
        //2.登录(指定用户名和密码)
        boolean b = ftpClient.login(username, password);
        if (!b) {
            log.info("ftp登陸超時");
            if (ftpClient.isConnected()) {
                // 断开连接
                ftpClient.disconnect();
            }
        }
        log.info("ftp登陸成功");
        // 设置字符编码
        ftpClient.setControlEncoding("UTF-8");
        //基本路径,一定存在
        String[] pathArray = targetPath.split("/");
        for (String path : pathArray) {
            if (path.equals("")) {
                continue;
            }
            //3.指定目录 返回布尔类型 true表示该目录存在
            boolean dirExsists = ftpClient.changeWorkingDirectory(path);
            //4.如果指定的目录不存在,则创建目录
            if (!dirExsists) {
                //此方式,每次,只能创建一级目录
                boolean flag = ftpClient.makeDirectory(path);
                if (!flag) {
                    System.out.println("文件目录创建失败!");
                    return false;
                }
                ftpClient.changeWorkingDirectory(path);
            }
        }
        log.info("重新指定上传文件的路径:" + targetPath);
        //重新指定上传文件的路径
//        ftpClient.changeWorkingDirectory(targetPath);
        //5.设置上传文件的方式
        ftpClient.setBufferSize(1024 * 1024 * 10);
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        /**
         * 6.执行上传
         * remote 上传服务后,文件的名称
         * local 文件输入流
         * 上传文件时,如果已经存在同名文件,会被覆盖
         */
        boolean uploadFlag = false;
        try {
            uploadFlag = ftpClient.storeFile(fileName, inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ftpClient.logout();
            ftpClient.disconnect();
        }
        if (uploadFlag) {
            System.out.println("上传成功!");
            return true;
        }
        return false;
    }

 

问题解决,记录一下爬坑的过程,顺便希望能帮到其他人。

 顺便记录下ftp文件下载

/**
     * 文件下载--FTP服务器
     */
    @LogRecord(name = "文件下载--FTP服务器")
    @GetMapping(value = "/v1/zdyl/downloadFile")
    public ResultJson downloadFileFtp(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String url = request.getParameter("url");
        if (url == null)
            throw new RRException("url is Empty!");
        URI uri = new URI(url);
        log.info("url:" + url);
        String path = uri.getPath();
        log.info("path:" + path);
        InputStream inputStream = UploadUtil.downloadFile(ftpConfig.getHost(), ftpConfig.getPort(), ftpConfig.getUsername(), ftpConfig.getPassword(), path);
        log.info("fileName:" + path.substring(path.lastIndexOf("/") + 1));
        response.setContentType("application/force-download");
        response.addHeader("Content-disposition", "attachment;fileName=" + path.substring(path.lastIndexOf("/") + 1));
        OutputStream os = response.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buf)) != -1) {
            os.write(buf, 0, len);
        }
        return null;
    }
/**
     * 功能:根据文件名称,下载文件流
     *
     * @return
     * @throws IOException
     */
    public static InputStream downloadFile(String hostname, int port, String username, String password, String remoteFilePath)
            throws IOException {
        InputStream in = null;
        FTPClient ftpClient = null;
        try {

            //实例化ftpClient
            ftpClient = new FTPClient();
            //设置登陆超时时间,默认是20s
            ftpClient.setDataTimeout(12000);
            //1.连接服务器
            ftpClient.connect(hostname, port);
            ftpClient.enterLocalPassiveMode();
            //2.登录(指定用户名和密码)
            boolean b = ftpClient.login(username, password);
            if (!b) {
                log.info("登陸超時");
                if (ftpClient.isConnected()) {
                    // 断开连接
                    ftpClient.disconnect();
                }
            }
            log.info("登陸成功");
            // 设置字符编码
            ftpClient.setControlEncoding("UTF-8");
            // 设置传输二进制文件
            ftpClient.setBufferSize(1024 * 1024 * 10);
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                throw new RRException("failed to connect to the FTP Server:");
            }
            // ftp文件获取文件

            in = ftpClient.retrieveFileStream(encodingPath(remoteFilePath));

        } catch (FTPConnectionClosedException e) {
            log.error("ftp连接被关闭!", e);
            throw e;
        } catch (Exception e) {
            log.error("ERR : upload file " + remoteFilePath + " from ftp : failed!", e);
            throw new RRException("ERR : upload file " + remoteFilePath + " from ftp : failed!");
        } finally {
            ftpClient.disconnect();
        }
        return in;
    }

    /**
     * 编码文件路径
     */
    private static String encodingPath(String path) throws UnsupportedEncodingException {
        // FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码
        return new String(path.replaceAll("//", "/").getBytes("GBK"), "iso-8859-1");
    }

 

posted @ 2021-04-01 17:57  william_zhao  阅读(3054)  评论(3编辑  收藏  举报