java ftp retrieveFile 较大文件丢失内容
今天发现用 如下方法下载一个2.2M的zip文件但是只下载了500K没有下载完全,但是方法 返回的却是true
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 较大文件丢失内容的更多相关文章
- 【Web应用】JAVA网络上传大文件报500错误
问题描述 当通过 JAVA 网站上传大文件,会报 500 错误. 问题分析 因为 Azure 的 Java 网站都是基于 IIS 转发的,所以我们需要关注 IIS 的文件上传限制以及 requestT ...
- java 分次读取大文件的三种方法
1. java 读取大文件的困难 java 读取文件的一般操作是将文件数据全部读取到内存中,然后再对数据进行操作.例如 Path path = Paths.get("file path&qu ...
- java处理excel-xlsx格式大文件的解决方案
1.第一次读取7M左右的ecxel文件,使用poi 库实现,参考了下面的博文. http://www.cnblogs.com/chenfool/p/3632642.html 使用上面的方法在 下面Wo ...
- java多线程实现复制大文件
有些开发的时候我们经常遇到这样一个问题,对大文件的处理.比如:日志文件.那么十几G的大文件.我们应该如何复制呢? 还有就是希望从本地和远程复制文件,文件都很大,10G级的如何办呢? 在这里我告诉你们, ...
- java使用WebUploader做大文件的分块和断点续传
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- 使用原生Java Web来实现大文件的上传
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- Java实现浏览器端大文件分片上传
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- java Io流输出指定文件的内容
package com.hp.io; import java.io.*; public class BufferedReaderTest{ /** *@param 想想 */ public st ...
- Java thymeleaf模板获取资源文件的内容
我们在某些时候可能需要获取配置文件properties中的配置信息,而不需要用Java传给模板,在模板中就可以直接获取 我们需要在resources/下定义国际化配置文件即可,注意名称必须中messa ...
随机推荐
- 前端知识点回顾——Javascript篇(二)
JavaScript的解析顺序 第一阶段:编译期 寻找关键字声明的变量.函数声明的变量,同时会对变量进行作用域的绑定 var声明的变量,在编译期会赋一个默认值undefined,变量提升的特性. ES ...
- 在 bat 批处理中运行多次 mvn
在 bat 中运行 mvn 命令会出现这种情况,构建命令执行完成后会停留在的 mvn.bat 中,必需手工输入 exit 后,才会回到原来的脚本中继续运行.这是怎么回事? 到 maven 的安装目录下 ...
- [go]gorhill/cronexpr用go实现crontab
// crontab基础 // linux crontab // 秒粒度, 年配置(2018-2099) // 哪一分钟(0-59),哪小时(0-23),哪天(1-31),哪月(1-12),星期几(0 ...
- CentOS / RHEL 配置yum源
CentOS / RHEL 配置yum源 */--> CentOS / RHEL 配置yum源 Table of Contents 1. 前言 2. 关于yum 2.1. yum是什么 2.2. ...
- MMORPG服务器架构
MMORPG服务器架构 一.摘要 1.网络游戏MMORPG整体服务器框架,包括早期,中期,当前的一些主流架构2.网络游戏网络层,包括网络协议,IO模型,网络框架,消息编码等.3.网络游戏的场景管理,A ...
- 在SSH里面远程启动ubuntu上的GUI程序
由于嵌入式开发板上是ubuntu系统,开发板接有显示器,现有一GUI程序需要在开发板显示器上实时显示,开发板与本地通过网络SSH连接,正常情况执行如:firefox,那么firefox会显示到本地,只 ...
- 转:使用ActiveX插件时object显示问题,div被object标签遮挡的解决方案
起因设计要求视频控制面板显示在视频界面上,如下图红框内所示.但是因为object不在文档流之中,所以不论别的元素设置z-index多高,都只会被object元素遮住而无法看到.object元素代码如下 ...
- 【POJ - 3262】Protecting the Flowers(贪心)
Protecting the Flowers 直接中文 Descriptions FJ去砍树,然后和平时一样留了 N (2 ≤ N ≤ 100,000)头牛吃草.当他回来的时候,他发现奶牛们正在津津有 ...
- 如何简单的编译v8动态库
按照google v8的官方提供的方法,在国内,完成编译简直太难了. 还好nodejs提供离线编译能力,稍微改造一下可以从node源码中直接编译纯净的v8动态库. 直接把v8解压出来的py/gpy文件 ...
- 【转载】VMware Workstation网络说明
1.什么是bridged(桥接模式)?答:在这种模式下,使用VMnet0虚拟交换机,虚拟操作系统就像是局域网中的一台独立的主机,与宿主计算机一样,它可以访问网内任何一台机器.在桥接模式下,可以手工配置 ...