zoukankan      html  css  js  c++  java
  • java ftp retrieveFile 较大文件丢失内容

    今天发现用  如下方法下载一个2.2M的zip文件但是只下载了500K没有下载完全,但是方法  返回的却是true

    boolean org.apache.commons.net.ftp.FTPClient.retrieveFile(String remote, OutputStream local) throws IOException
     
    根据网上查的资料设置了
     

    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
    ftp.configure(conf);

    发现有时候成功有时候失败(有时候只下载了1.8M就返回true了)

    后来又设置了ftp.setDataTimeout(300 * 1000);

    ftp.setReceiveBufferSize(1024 * 1024);
    ftp.setBufferSize(1024 * 1024);

    试了几次没有发现只下载了部分(比如1.8M)的问题了,后续再继续观察

    20190919更新

    部署到正式环境发现CKS的ftp下载还是有下载不完全问题,我又改了一下程序,判断下载下来的文件大小和ftp上的文件大小是不是size相等,不相等就不删除,等待下次重新下载。如果是zip文件还可以判断一下是否是能够解压的zip再删除。具体代码如下

    public static boolean downloadFile(String ftpOdmPath, Integer port, OdmInfo odmInfo, String downloadLocalPath){
    boolean downloadStatus = false;


    FTPClient ftp = new FTPClient();
    ftp.setControlEncoding("UTF-8");

    try {
    int reply;
    ftp.setDefaultTimeout(30 * 1000);
    ftp.setConnectTimeout(30 * 1000);
    ftp.setDataTimeout(300 * 1000);

    FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
    ftp.configure(conf);

    logger.info("start to connect ftp server");
    ftp.connect(odmInfo.getFtpserver(), port);// 连接FTP服务器
    logger.info("connect ftp server success");
    ftp.login(odmInfo.getFtpusername(), odmInfo.getFtppwd());// 登录
    //设置ftp为被动模式,解决有时候ftp会卡住问题
    ftp.enterLocalPassiveMode();

    ftp.setReceiveBufferSize(1024 * 1024);
    ftp.setBufferSize(1024 * 1024);

    logger.info("login ftp server success");
    reply = ftp.getReplyCode();
    logger.info("reply======"+reply);
    if (!FTPReply.isPositiveCompletion(reply)) {

    ftp.disconnect();
    return downloadStatus;
    }
    ftp.setFileType(FTPClient.BINARY_FILE_TYPE);

    //切换FTP目录
    logger.info("ftpOdmPath======"+ftpOdmPath);
    boolean changeDirStatus=ftp.changeWorkingDirectory(ftpOdmPath);
    if(changeDirStatus)
    {
    FTPFile[] ftpFiles = ftp.listFiles();
    for(FTPFile file : ftpFiles){
    long fileSize=file.getSize();
    OutputStream os=null;
    boolean retrieveStatus=false;
    try {
    logger.info("download file======"+downloadLocalPath + "/" + file.getName());
    File localFile = new File(downloadLocalPath + "/" + file.getName());
    if (!localFile.getParentFile().exists()) {
    localFile.getParentFile().mkdirs();
    }
    if(localFile.isDirectory())
    {
    continue;
    }
    os = new FileOutputStream(localFile);
    retrieveStatus=ftp.retrieveFile(file.getName(), os);
    logger.info("ftp download file======"+file.getName()+"===="+retrieveStatus);
    if(os!=null)
    {
    os.flush();
    }


    } catch (Exception e) {
    // TODO Auto-generated catch block
    logger.error("",e);
    } finally {
    if(os!=null)
    {
    os.close();
    }
    }

    //如果下载成功删除ftp上的文件,并且文件大小和ftp上的一样才删除文件,如果是zip文件还要判断一下是不是zip文件再删除ftp上的文件
    if(retrieveStatus)
    {
    try {
    File localFileCheckSize = new File(downloadLocalPath + "/" + file.getName());
    long localFileSize=localFileCheckSize.length();

    logger.info("ftp file size======"+fileSize+"===local file size===="+localFileSize);
    if(fileSize==localFileSize)
    {
    if(file.getName()!=null&&file.getName().endsWith(".zip"))
    {
    if(CompressUtil.checkZipFile(localFileCheckSize))
    {
    ftp.dele(file.getName());
    logger.info("delete ftp file======"+file.getName());
    }
    else
    {
    logger.info("download from ftp file is not zip file======"+downloadLocalPath + "/" + file.getName());
    }
    }
    else
    {
    ftp.dele(file.getName());
    logger.info("delete ftp file======"+file.getName());
    }

    }
    } catch (Exception e) {
    // TODO Auto-generated catch block
    logger.error("",e);
    }
    }

    }
    }
    ftp.logout();
    downloadStatus = true;
    logger.info("download file success");
    } catch (Exception e) {
    logger.error("",e);
    downloadStatus = false;
    } finally{
    if(ftp.isConnected()){
    try{
    ftp.disconnect();
    }catch(IOException e){
    logger.error("",e);
    downloadStatus = false;
    }
    }

    }
    return downloadStatus;
    }

     如下网上的文章是解决这次问题的参考

    https://blog.csdn.net/dise0092/article/details/100765177

    在使用java的ftp下载服务器上的文件获取文件的byte[],然后对byte进行加密传输时,

           注意是要获取byte[],而不是下载文件到本地;

    发现下载的byte[]大小总是小于文件实际大小,并且下载的大小是变化的

    到网上查阅发现,ftp传输是不稳定的,会随网络情况波动;

    所以对下载的方法进行了修改;

    import sun.net.ftp.FtpClient;
    import sun.net.ftp.FtpProtocolException;

    public String download(String ftpFile, FtpClient ftpClient) {

    InputStream is = null;
    byte[] data = null;
    try {
    // 获取ftp上的文件
    long size=ftpClient.getSize(ftpFile);
    System.out.println(ftpClient.getSize(ftpFile));
    is = ftpClient.getFileStream(ftpFile);
    // System.out.println(is.available());

    int count =is.available();
    System.out.println("count:"+count);

    while (count>0 || (data==null?0:data.length)<size) {// 获取到的大小小于文件大小也进入
    byte[] b = new byte[count];
    is.read(b);
    System.out.println("b:"+b.length);
    data= byteMerger(b,data);
    count = is.available();
    }

    is.close();

    ftpClient.close();

    }catch (FtpProtocolException e) {
    e.printStackTrace();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    // 加密
    System.out.println("data size:"+data.length);
    String encodeBase64Str =org.apache.commons.codec.binary.Base64.encodeBase64String(data);

    return encodeBase64Str;
    }

    // 参考 https://blog.csdn.net/shb2058/article/details/52637213
    public static byte[] byteMerger(byte[] byte1, byte[] byte2){
    if (byte1==null && byte2!=null){
    return byte2;
    }

    if (byte2 == null && byte1!=null){
    return byte1;
    }

    if (byte2 == null && byte1 ==null){
    return null;
    }
    byte[] byte3 = new byte[byte1.length+byte2.length];
    System.arraycopy(byte1, 0, byte3, 0, byte1.length);
    System.arraycopy(byte2, 0, byte3, byte1.length, byte2.length);
    return byte3;
    }

    /***
    * 连接ftp
    * @param url
    * @param port
    * @param username
    * @param password
    * @return
    */
    public FtpClient connectFTP(String url, int port, String username, String password) {
    //创建ftp
    FtpClient ftp = null;
    try {
    //创建地址
    SocketAddress addr = new InetSocketAddress(url, port);
    //连接
    ftp = FtpClient.create();
    ftp.connect(addr);
    //登陆
    ftp.login(username, password.toCharArray());
    ftp.setBinaryType();

    ftp.enablePassiveMode(true);//这句最好加告诉对面服务器开一个端口

    } catch (FtpProtocolException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    return ftp;
    }
    运行发现果然波动是很大的

    参考:

    https://blog.csdn.net/shb2058/article/details/52637213

    网上还有个说法,下午试试

    如果小文件可以下载,但是大文件下载后缺少几字节之类的话,可以设置ftpClient.setFileType(FTP.BINARY_FILE_TYPE)以二进制去传输,如果是大文件直接完全下载不了,卡死的话,建议设置为ftpClient.enterLocalPassiveMode(),并且设置超时时间,做一个5-10次的for循环,保证能够下载下来。

  • 相关阅读:
    (十七)物联网之 WIFI 一键配网 smartConfig 浅析
    mac 下设置jdk 路径,设置hadoop 路径
    mac 下配置 git
    mysql mac  安装修改初始密码
    linux 下安装 mysql5.7.16安装
    linux 安装nexus
    linux 安装maven
    linux 下安装mongodb
    转发和重定向
    spring mvc controller间跳转 重定向 传参
  • 原文地址:https://www.cnblogs.com/xiaohanlin/p/11473752.html
Copyright © 2011-2022 走看看