今天发现用  如下方法下载一个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. MATLAB学习(九)系统聚类

        >> X=rand(100,2); >> Y=pdist(X,'euclidean'); >> Z = linkage(Y,'average'); > ...

  2. C++typedef的详细用法

    转自知乎的一段解释: 作者:知乎用户链接:https://www.zhihu.com/question/29798061/answer/144423125来源:知乎著作权归作者所有.商业转载请联系作者 ...

  3. 在Spring中配置jdbc为什么不能用${username}问题

    楼主在spring中配置jdbc时,引用的是dbcp.jar包,在dataSource.properties配置文件中,有mysql用户名,楼主自然的选择了使用username,密码是root, 然后 ...

  4. 代码托管至Github

    昨天突然之间觉得作为一个iOS程序员,没有在github上提交过自己的代码真是一大遗憾,不管是自己写的优秀的代码还是刚开始学习,用来学习练手的项目.然后我就很想要学习怎么往github上提交代码,很不 ...

  5. Centos7 搭建Svn+Apache服务器

    Svn客户端搭建 1.yum install subversion 2.查看安装版本 svnserve --version 3.创建SVN版本库目录 mkdir -p /opt/svn 4.创建版本库 ...

  6. web系统认证与鉴权中的一些问题

    认证鉴权系统的初心: 空间管理: 1.他是谁? 他登陆了没有? 2.他要做什么? 2.1 他要使用什么功能? 他是否有这个功能的权限. 2.2 他要使用这个功能做什么操作? 他是否有这个功能的这个操作 ...

  7. ERROR 2002 (HY000): Can 't connect to local MySQL server through socket '/tmp/mysql.sock '(2) "

    找不到mysql.sock这个文件 如果在你操作安装提示创建该文件,重启服务器还是提示这个错误可以试一下 mysql -uroot -h 127.0.0.1 -p 应该是可以直接进入 具体处理方法 重 ...

  8. 【VS开发】list控件的InsertColumn方法出错

    今天在写一个获取磁盘信息的小程序,通过list控件显示各磁盘信息.我在属性页(CPropertyPage)的构造函数中,调用list控件的InsertColumn方法,编译链接都通过了,但运行时冒出了 ...

  9. C#枚举扩展方法,获取枚举值的描述值以及获取一个枚举类下面所有的元素

    /// <summary> /// 枚举扩展方法 /// </summary> public static class EnumExtension { private stat ...

  10. flask内置的信号

    from flask import Flask,request,template_rendered,render_template,got_request_exception from signals ...