今天发现用  如下方法下载一个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; 
     }

 

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


 

在使用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;
    }

    // 参考 
    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;
    }


运行发现果然波动是很大的

 


 

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

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