java ftp retrieveFile 較大文件丟失內容


 

今天發現用  如下方法下載一個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循環,保證能夠下載下來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM