ftp上傳與下載文件

準備工做

服務器已經配置好ftp服務

服務器linux centos 7.4 搭建ftp服務器:http://www.javashuo.com/article/p-mudyluny-kt.htmlhtml

須要用到的jar包:

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.3</version>
</dependency>

配置文件

  • application.yml
# 配置ftp服務器信息
ftp: 
  # ftp服務器的IP地址
  url: 127.0.0.0
  # 默認端口是21
  port: 21
  username: ftpuser
  password: ftpuser
  # ftp服務器存放文件的路徑
  remotePath: /data/ftp
  # 本地須要上傳的文件的路徑
  localDir: D:/test
  # ftp上文件下載到本地存放的路徑
  downDir: D:/test
  • FtpConfig配置信息類
@Getter
@Component
public class FtpConfig {
    /**
     * ftp服務器地址
     */
    @Value("${ftp.url}")
    private String url;
    
    /**
     * ftp服務器端口
     */
    @Value("${ftp.port}")
    private int port;
    
    /**
     * ftp服務器用戶名
     */
    @Value("${ftp.username}")
    private String username;
    
    /**
     * ftp服務器密碼
     */
    @Value("${ftp.password}")
    private String password;
    
    /**
     * ftp服務器存放文件的路徑
     */
    @Value("${ftp.remotePath}")
    private String remotePath;
    
    /**
     * 本地須要上傳的文件的路徑
     */
    @Value("${ftp.localDir}")
    private String localDir;
    
    /**
     * 下載文件時,存放在本地的路徑
     */
    @Value("${ftp.downDir}")
    private String downDir;
    
}

工具類FtpUtil內容

@Slf4j(topic="文件上傳/下載===ftp服務器:")
public class FtpUtil {
    private static FTPClient mFTPClient = new FTPClient();
    private static FtpUtil ftp = new FtpUtil();
    
    public FtpUtil() {
        // 在控制檯打印操做過程
         mFTPClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
    }


    /**
     * 上傳文件到ftp服務器
     */
    public static boolean ftpUpload(String fileName, String ftpUrl, int ftpPort,
            String ftpUsername, String ftpPassword, String ftpLocalDir, String ftpRemotePath) {
        boolean result = false;
        try {
            boolean isConnection = ftp.openConnection(ftpUrl, ftpPort, ftpUsername, ftpPassword);
            if (isConnection) {
                boolean isSuccess = ftp.upload(ftpRemotePath, ftpLocalDir + "/" + fileName);
                if (isSuccess) {
                    log.info("文件上傳成功!");
                    result = true;
                } else {
                    log.info("文件上傳失敗!");
                    result = false;
                }
                ftp.logout();
            } else {
                log.info("連接ftp服務器失敗,請檢查配置信息是否正確!");
                result = false;
            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 從ftp服務器下載文件到本地
     */
    public static boolean ftpDownload(String fileName, String ftpUrl, int ftpPort,
            String ftpUsername, String ftpPassword, String ftpRemotePath, String ftpDownDir) {
        boolean result = false;
        try {
            boolean isConnection = ftp.openConnection(ftpUrl, ftpPort, ftpUsername, ftpPassword);
            if (isConnection) {
                boolean isDownloadOk = ftp.downLoad(fileName, ftpDownDir);
                boolean isCreateOk = ftp.createDirectory(ftpRemotePath, ftp.mFTPClient);
                if (isDownloadOk && isCreateOk) {
                    log.info("文件下載成功!");
                    result = true;
                } else {
                    log.info("文件下載失敗!");
                    result = false;
                }
                ftp.logout();
            } else {
                log.info("連接ftp服務器失敗,請檢查配置信息是否正確!");
                result = false;
            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;

    }

    /**
     * 鏈接ftp服務器
     * 
     * @param host
     *            ip地址
     * @param port
     *            端口號
     * @param account
     *            帳號
     * @param pwd
     *            密碼
     * @return 是否鏈接成功
     * @throws SocketException
     * @throws IOException
     */
    private boolean openConnection(String host, int port, String account, String pwd)
            throws SocketException, IOException {
        mFTPClient.setControlEncoding("UTF-8");
        mFTPClient.connect(host, port);

        if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
            mFTPClient.login(account, pwd);
            if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
                System.err.println(mFTPClient.getSystemType());
                FTPClientConfig config = new FTPClientConfig(mFTPClient.getSystemType().split(" ")[0]);
                config.setServerLanguageCode("zh");
                mFTPClient.configure(config);
                return true;
            }
        }
        disConnection();
        return false;
    }

    /**
     * 登出並斷開鏈接
     */
    public void logout() {
        System.err.println("logout");
        if (mFTPClient.isConnected()) {
            System.err.println("logout");
            try {
                mFTPClient.logout();
                disConnection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 斷開鏈接
     */
    private void disConnection() {
        if (mFTPClient.isConnected()) {
            try {
                mFTPClient.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 下載文件到本地地址
     * 
     * @param remotePath
     *            遠程地址
     * @param loacal
     *            本地地址
     * @throws IOException
     */
    public boolean downLoad(String remotePath, String localDir) throws IOException {
        // 進入被動模式
        mFTPClient.enterLocalPassiveMode();
        // 以二進制進行傳輸數據
        mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
        FTPFile[] ftpFiles = mFTPClient.listFiles(remotePath);
        if (ftpFiles == null || ftpFiles.length == 0) {
            log.info("遠程文件不存在");
            return false;
        } else if (ftpFiles.length > 1) {
            log.info("遠程文件是文件夾");
            return false;
        }
        long lRemoteSize = ftpFiles[0].getSize();
        // 本地文件的地址
        File localFileDir = new File(localDir);
        if (!localFileDir.exists()) {
            localFileDir.mkdirs();
        }
        File localFile = new File(localFileDir, ftpFiles[0].getName());
        long localSize = 0;
        FileOutputStream fos = null;
        if (localFile.exists()) {
            if (localFile.length() == lRemoteSize) {
                System.err.println("已經下載完畢");
                return true;
            } else if (localFile.length() < lRemoteSize) {
                // 要下載的文件存在,進行斷點續傳
                localSize = localFile.length();
                mFTPClient.setRestartOffset(localSize);
                fos = new FileOutputStream(localFile, true);
            }
        }
        if (fos == null) {
            fos = new FileOutputStream(localFile);
        }
        InputStream is = mFTPClient.retrieveFileStream(remotePath);
        byte[] buffers = new byte[1024];
        long step = lRemoteSize / 10;
        long process = localSize / step;
        int len = -1;
        while ((len = is.read(buffers)) != -1) {
            fos.write(buffers, 0, len);
            localSize += len;
            long newProcess = localSize / step;
            if (newProcess > process) {
                process = newProcess;
                System.err.println("下載進度:" + process);
            }
        }
        is.close();
        fos.close();
        boolean isDo = mFTPClient.completePendingCommand();
        if (isDo) {
            System.err.println("下載成功");
        } else {
            System.err.println("下載失敗");
        }
        return isDo;

    }

    /**
     * 建立遠程目錄
     * 
     * @param remote
     *            遠程目錄
     * @param ftpClient
     *            ftp客戶端
     * @return 是否建立成功
     * @throws IOException
     */
    public boolean createDirectory(String remote, FTPClient ftpClient) throws IOException {
        String dirctory = remote.substring(0, remote.lastIndexOf("/") + 1);
        if (!dirctory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(dirctory)) {
            int start = 0;
            int end = 0;
            if (dirctory.startsWith("/")) {
                start = 1;
            }
            end = dirctory.indexOf("/", start);
            while (true) {
                String subDirctory = remote.substring(start, end);
                if (!ftpClient.changeWorkingDirectory(subDirctory)) {
                    if (ftpClient.makeDirectory(subDirctory)) {
                        ftpClient.changeWorkingDirectory(subDirctory);
                    } else {
                        System.err.println("建立目錄失敗");
                        return false;
                    }
                }
                start = end + 1;
                end = dirctory.indexOf("/", start);
                if (end <= start) {
                    break;
                }
            }
        }
        return true;
    }

    /**
     * 上傳的文件
     * 
     * @param remotePath
     *            上傳文件的路徑地址(文件夾地址)
     * @param localPath
     *            本地文件的地址
     * @throws IOException
     *             異常
     */
    public boolean upload(String remotePath, String localPath) throws IOException {
        // 進入被動模式
        mFTPClient.enterLocalPassiveMode();
        // 以二進制進行傳輸數據
        mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
        File localFile = new File(localPath);
        if (!localFile.exists()) {
            System.err.println("本地文件不存在");
            return false;
        }
        String fileName = localFile.getName();
        if (remotePath.contains("/")) {
            boolean isCreateOk = createDirectory(remotePath, mFTPClient);
            if (!isCreateOk) {
                System.err.println("文件夾建立失敗");
                return false;
            }
        }

        // 列出ftp服務器上的文件
        FTPFile[] ftpFiles = mFTPClient.listFiles(remotePath);
        long remoteSize = 0l;
        String remoteFilePath = remotePath + "/" + fileName;
        if (ftpFiles.length > 0) {
            FTPFile mFtpFile = null;
            for (FTPFile ftpFile : ftpFiles) {
                if (ftpFile.getName().endsWith(fileName)) {
                    mFtpFile = ftpFile;
                    break;
                }
            }
            if (mFtpFile != null) {
                remoteSize = mFtpFile.getSize();
                if (remoteSize == localFile.length()) {
                    System.err.println("文件已經上傳成功");
                    return true;
                }
                if (remoteSize > localFile.length()) {
                    if (!mFTPClient.deleteFile(remoteFilePath)) {
                        System.err.println("服務端文件操做失敗");
                    } else {
                        boolean isUpload = uploadFile(remoteFilePath, localFile, 0);
                        System.err.println("是否上傳成功:" + isUpload);
                    }
                    return true;
                }
                if (!uploadFile(remoteFilePath, localFile, remoteSize)) {
                    System.err.println("文件上傳成功");
                    return true;
                } else {
                    // 斷點續傳失敗刪除文件,從新上傳
                    if (!mFTPClient.deleteFile(remoteFilePath)) {
                        System.err.println("服務端文件操做失敗");
                    } else {
                        boolean isUpload = uploadFile(remoteFilePath, localFile, 0);
                        System.err.println("是否上傳成功:" + isUpload);
                    }
                    return true;
                }
            }
        }

        boolean isUpload = uploadFile(remoteFilePath, localFile, remoteSize);
        System.err.println("是否上傳成功:" + isUpload);
        return isUpload;
    }

    /**
     * 上傳文件
     * 
     * @param remoteFile
     *            包含文件名的地址
     * @param localFile
     *            本地文件
     * @param remoteSize
     *            服務端已經存在的文件大小
     * @return 是否上傳成功
     * @throws IOException
     */
    private boolean uploadFile(String remoteFile, File localFile, long remoteSize) throws IOException {
        long step = localFile.length() / 10;
        long process = 0;
        long readByteSize = 0;
        RandomAccessFile randomAccessFile = new RandomAccessFile(localFile, "r");
        OutputStream os = mFTPClient.appendFileStream(remoteFile);
        if (remoteSize > 0) {
            // 已經上傳一部分的時候就要進行斷點續傳
            process = remoteSize / step;
            readByteSize = remoteSize;
            randomAccessFile.seek(remoteSize);
            mFTPClient.setRestartOffset(remoteSize);
        }
        byte[] buffers = new byte[1024];
        int len = -1;
        while ((len = randomAccessFile.read(buffers)) != -1) {
            os.write(buffers, 0, len);
            readByteSize += len;
            long newProcess = readByteSize / step;
            if (newProcess > process) {
                process = newProcess;
                System.err.println("當前上傳進度爲:" + process);
            }
        }
        os.flush();
        randomAccessFile.close();
        os.close();
        boolean result = mFTPClient.completePendingCommand();
        return result;
    }

}

訪問測試

@RestController
@RequestMapping(value = "/ftp")
@Slf4j(topic="請求ftp服務器")
public class FtpController {
    @Autowired
    FtpConfig ftpConfig;

    @GetMapping("/upload")
    public String upload() {
        String fileName = "uploadfile.txt";
        boolean result = FtpUtil.ftpUpload(fileName, ftpConfig.getUrl(),ftpConfig.getPort(),ftpConfig.getUsername(),
                ftpConfig.getPassword(), ftpConfig.getLocalDir(), ftpConfig.getRemotePath());
        if (result) {
            log.info("=======上傳文件"+ fileName +"成功=======");
        } else {
            log.info("=======上傳文件"+ fileName +"失敗=======");
        }
        return result?"上傳成功":"上傳失敗";

    }

    @GetMapping("/download")
    public String download(){
        String fileName = "welcome.txt";
        boolean result = FtpUtil.ftpDownload(fileName, ftpConfig.getUrl(),ftpConfig.getPort(),ftpConfig.getUsername(),
                ftpConfig.getPassword(), ftpConfig.getRemotePath(), ftpConfig.getLocalDir() );
        if (result) {
            log.info("=======下載文件"+ fileName +"成功=======");
        } else {
            log.info("=======下載文件"+ fileName +"失敗=======");
        }
        return result?"下載成功":"下載失敗";
    }
    
}

測試結果1: 上傳成功

測試結果2: 下載成功java

代碼 github 地址:https://github.com/mmzsblog/springboot-FtpUtil

linux

相關文章
相關標籤/搜索