今天发现用  如下方法下载一个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循环,保证能够下载下来。

java ftp retrieveFile 较大文件丢失内容的更多相关文章

  1. 【Web应用】JAVA网络上传大文件报500错误

    问题描述 当通过 JAVA 网站上传大文件,会报 500 错误. 问题分析 因为 Azure 的 Java 网站都是基于 IIS 转发的,所以我们需要关注 IIS 的文件上传限制以及 requestT ...

  2. java 分次读取大文件的三种方法

    1. java 读取大文件的困难 java 读取文件的一般操作是将文件数据全部读取到内存中,然后再对数据进行操作.例如 Path path = Paths.get("file path&qu ...

  3. java处理excel-xlsx格式大文件的解决方案

    1.第一次读取7M左右的ecxel文件,使用poi 库实现,参考了下面的博文. http://www.cnblogs.com/chenfool/p/3632642.html 使用上面的方法在 下面Wo ...

  4. java多线程实现复制大文件

    有些开发的时候我们经常遇到这样一个问题,对大文件的处理.比如:日志文件.那么十几G的大文件.我们应该如何复制呢? 还有就是希望从本地和远程复制文件,文件都很大,10G级的如何办呢? 在这里我告诉你们, ...

  5. java使用WebUploader做大文件的分块和断点续传

    版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...

  6. 使用原生Java Web来实现大文件的上传

    版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...

  7. Java实现浏览器端大文件分片上传

    版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...

  8. java Io流输出指定文件的内容

    package com.hp.io; import java.io.*; public class  BufferedReaderTest{ /** *@param   想想 */ public st ...

  9. Java thymeleaf模板获取资源文件的内容

    我们在某些时候可能需要获取配置文件properties中的配置信息,而不需要用Java传给模板,在模板中就可以直接获取 我们需要在resources/下定义国际化配置文件即可,注意名称必须中messa ...

随机推荐

  1. spring clound gateway 上传文件,中文文件名乱码解决办法

    先说解决办法吧: 有三种解决办法 1 ,zuul官方给出了解决方案,使用/zuul开头的请求可以避免中文名乱码以及支持大文件上传 域名是 testgateway.com  接口是  api/image ...

  2. 如何配置git send-email相关的邮箱信息?

    关键是配置smtpserver,请参考此处

  3. 发布机制-灰度发布-例子:QZone

    ylbtech-发布机制-灰度发布-例子:QZone QZone是另外一个采用灰度发布的例子.大家都知道,QZone在过去的一年中改进是巨大的,从以前慢悠悠的老爷爷变成了一个充满青春活力的小伙子.其中 ...

  4. Android:通过systrace进行性能分析

    一.Systrace 简介 Systrace 允许您在系统级别(如SurfaceFlinger.WindowManagerService等Framework部分关键模块.服务.View系统等)收集和检 ...

  5. mybatis之动态SQL操作之删除

    /** * 持久层 */ public class StudentDao { /** * 动态SQL--删除 */ public void dynaSQLwithDelete(int... ids) ...

  6. python -v 和-V

    python -v 小写v:这是版本信息,包括库版本 python -V 大写v:只看python的版本

  7. 九十四:CMS系统之cms后台登录限制

    装饰器,验证当前session中是否存在定义的user_id,没有就重定向到登录页 from flask import session, redirect, url_forfrom functools ...

  8. weblogic12.1.3部署应用程序

    weblogic12.1.3部署应用程序请参照:https://www.cnblogs.com/xdp-gacl/p/4143413.html

  9. gdb调试caffe工程

    环境:UBUNTU 16.04 CMake caffe 1.0.0-rc3 1.首先编译caffe为debug版本: 在caffe根目录下编辑CMakeFileList.txt,加入如下几行: SET ...

  10. AES 加密算法的原理详解

    AES 加密算法的原理详解 本教程摘选自 https://blog.csdn.net/qq_28205153/article/details/55798628 的原理部分. AES简介 高级加密标准( ...