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");
    }

 


免責聲明!

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



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