retrievefile文件字节为0_java ftp retrieveFile 较大文件丢失内容

本文详细记录了解决Java FTP下载大文件时出现内容丢失的问题,包括设置超时时间、缓冲区大小,以及通过进入被动模式来避免网络波动导致的下载不完整。还提供了一个检查下载文件完整性的方法,对于.zip文件还会验证是否可解压。最后,引用了相关文章作为参考。
摘要由CSDN通过智能技术生成

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)

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循环,保证能够下载下来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值