java FTP客戶端獲取文件流假死問題

 依賴 hutool 

 

FTP配置

inspection.data.ftp.host=172.26.1.41
inspection.data.ftp.port=21
inspection.data.ftp.user=6c
inspection.data.ftp.password=6cqq123
inspection.data.ftp.charsetName=GBK

FTP配置類

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@Data
@ConfigurationProperties(prefix = "inspection.data.ftp")
public class FtpParamProperties {

    // ftp ip
    private String host;
    // ftp 端口
    private int port;
    // ftp 用戶
    private String user;
    // ftp 密碼
    private String password;
    // ftp 編碼
    private String charsetName;
}

 

FTP工具類


import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.http.ContentType;
import com.cdtye.itps.cms.config.FtpParamProperties;
import com.cdtye.itps.cms.model.dto.DownloadDto;
import com.cdtye.itps.cms.model.dto.FtpPathTree;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;

@Component
public class FtpUtil {

    static FtpParamProperties ftpParamProperties;

    public static Ftp getConnect() {
        return new Ftp(ftpParamProperties.getHost(), ftpParamProperties.getPort()
                , ftpParamProperties.getUser(), ftpParamProperties.getPassword()
                , Charset.forName(ftpParamProperties.getCharsetName()));
    }

    public static void downLoad(DownloadDto downloadDto, HttpServletResponse response) {
        if (Objects.isNull(downloadDto)) {
            throw new RuntimeException("下載參數不能爲空");
        }
        if (StringUtils.isBlank(downloadDto.getFileName())) {
            throw new RuntimeException("下載參數中文件名不能爲空");
        }
        if (StringUtils.isBlank(downloadDto.getUrl())) {
            throw new RuntimeException("下載參數中url不能爲空");
        }
        response.reset();
        response.setContentType(ContentType.OCTET_STREAM.getValue());
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + downloadDto.getFileName());

        if (StringUtils.isNotBlank(downloadDto.getUrl())) {
            downFormUrl(downloadDto, response);
        }
    }

    private static void downFormUrl(DownloadDto downloadDto, HttpServletResponse response) {
        try (InputStream stream = URLUtil.getStream(URLUtil.toUrlForHttp(URLUtil.encodeFragment(downloadDto.getUrl())))) {
            byte[] buff = new byte[1024];
            OutputStream os = response.getOutputStream();
            int i = 0;
            while ((i = stream.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException("下載文件異常", e);
        }
    }

    public static FtpPathTree recursionLs(String rootPath, Filter<FTPFile> filter) throws Exception {
        if (StringUtils.isBlank(rootPath)) {
            throw new RuntimeException("目錄路徑不能爲空");
        }
        FtpPathTree ftpPathTree = new FtpPathTree();
        try (Ftp ftp = FtpUtil.getConnect()) {
            if (!ftp.exist(rootPath)) {
                throw new RuntimeException("目錄不存在");
            }
            ftpPathTree.setFileName(rootPath);
            ftpPathTree.setFileFullPath(rootPath);
            List<FTPFile> ftpFiles = ftp.lsFiles(rootPath, filter);
            if (CollectionUtils.isNotEmpty(ftpFiles)) {
                recursionChild(ftpFiles, ftp, ftpPathTree, filter);
            }
        } catch (Exception e) {
            throw e;
        }
        return ftpPathTree;
    }


    private static FtpPathTree recursionChild(List<FTPFile> ftpFiles, Ftp ftp, FtpPathTree ftpPathTree, Filter<FTPFile> filter) {
        if (CollectionUtils.isNotEmpty(ftpFiles)) {
            for (FTPFile ftpFile : ftpFiles) {
                String currentPath = ftpPathTree.getFileFullPath() + "/" + ftpFile.getName();
                if (ftpFile.isDirectory()) {
//                    Filter<FTPFile> filterDirectory = (f) -> Objects.nonNull(f);
                    List<FTPFile> ftpFiles1 = ftp.lsFiles(currentPath, filter);
                    if (CollectionUtils.isNotEmpty(ftpFiles1)) {
                        FtpPathTree ftpPathTree2 = new FtpPathTree();
                        ftpPathTree2.setFileName(ftpFile.getName());
                        ftpPathTree2.setFileFullPath(currentPath);
                        ftpPathTree.getChilds().add(recursionChild(ftpFiles1, ftp, ftpPathTree2, filter));
                    } else {
                        FtpPathTree ftpPathTree1 = new FtpPathTree();
                        ftpPathTree1.setFileName(ftpFile.getName());
                        ftpPathTree1.setFileFullPath(currentPath);
                        ftpPathTree.getChilds().add(ftpPathTree1);
                    }
                } else {
                    FtpPathTree ftpPathTree1 = new FtpPathTree();
                    ftpPathTree1.setFileName(ftpFile.getName());
                    ftpPathTree1.setFileFullPath(currentPath);
                    ftpPathTree1.setFileFlag(Boolean.TRUE);
                    ftpPathTree.getChilds().add(ftpPathTree1);
                }
            }
        }
        return ftpPathTree;
    }

    public static void recursionFile(List<FtpPathTree> ftpPathTrees, FtpPathTree ftpPathTree) {
        if (Objects.nonNull(ftpPathTree)) {
            if (ftpPathTree.getFileFlag()) {
                ftpPathTrees.add(ftpPathTree);
            } else {
                if (CollectionUtils.isNotEmpty(ftpPathTree.getChilds())) {
                    for (FtpPathTree child : ftpPathTree.getChilds()) {
                        recursionFile(ftpPathTrees, child);
                    }
                }
            }
        }
    }

    public static void downloadFile(String fileFullPath, HttpServletResponse response) throws Exception {
        if (StringUtils.isBlank(fileFullPath)) {
            throw new RuntimeException("文件路徑不能爲空!");
        }
        try (ServletOutputStream outputStream = response.getOutputStream(); Ftp ftp = FtpUtil.getConnect()) {
            if (!ftp.exist(fileFullPath)) {
                throw new RuntimeException("文件不存在!");
            }
            if (ftp.isDir(fileFullPath)) {
                throw new RuntimeException("只能下載文件!");
            }
            response.reset();
            String fullFileName = FileNameUtil.getName(fileFullPath);
            String filePath = StringUtils.substringBefore(fileFullPath, fullFileName);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'"
                    + URLEncoder.encode(fullFileName, "UTF-8").replace("+", "%20"));
            ftp.download(filePath, fullFileName, outputStream);
            outputStream.flush();
        }

    }

    @Autowired
    public void setFtpParamProperties(FtpParamProperties ftpParamProperties) {
        FtpUtil.ftpParamProperties = ftpParamProperties;
    }
}

測試類

import cn.hutool.extra.ftp.Ftp;
import com.cdtye.itps.cms.util.FtpUtil;
import org.apache.commons.net.ftp.FTPClient;

import java.io.InputStream;
import java.util.Objects;

public class FTPTest {
    public static void main(String[] args) {
        try (Ftp ftp = FtpUtil.getConnect()) {
            FTPClient client = ftp.getClient();
            InputStream inputStream = null;
                try {
                    // 開始主動模式
                    client.enterLocalPassiveMode();
                    inputStream = client.retrieveFileStream("FTP路徑");
                    if (Objects.nonNull(inputStream)) {
                        // 拿到流做事情
                    }
                } catch (Exception e) {
                } finally {
                    if (Objects.nonNull(inputStream)) {
                        inputStream.close();
                    }
                    //重點是這兩行,解決假死問題
                    client.sendNoOp();
                    client.completePendingCommand();
                }
        } catch (Exception e) {
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章