问题
My Android app (Java 8, min SDK 24, target SDK 27) downloads images from an FTP server, using Apache's FTPClient
(version 3.6).
There are a couple of smaller .jpg images (around 12kb each) that always download completely but all of the bigger .png images (8+ mb each) show up black in my app. The files on the server look fine, so I downloaded the images from the emulator:
Windows' "Photo" app displays a black, horizontal bar at the bottom of all the affected images and they are all missing a couple of bytes (according to Windows' file explorer).
Reading the downloaded image with BitmapFactory.decodeFile(....)
on a real device returns a null
Bitmap
, even though the file exists.
My code (runs on a background thread):
public void downloadFiles(String remoteFolder, String localFolder, ArrayList<String> filenames) {
//login here
ftpClient.setConnectTimeout(10000);
ftpClient.setDefaultTimeout(10000);
OutputStream out = null;
try {
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
if(ftpClient.changeWorkingDirectory(remoteFolder)) {
for(String filename : filenames) {
FTPFile[] singleFile = ftpClient.listFiles(filename);
if(singleFile != null && singleFile.length > 0) { //check if file exists
String localPath = localFolder + File.separator + filename;
out = new FileOutputStream(localPath);
if(!ftpClient.retrieveFile(filename, out)) {
//Set error message here
out.close();
break;
}
out.close();
} else {
//Another error message here
break;
}
}
}
} catch (IOException e) {
//And another error message here
} finally {
try {
if(out!=null) { out.close(); }
} catch(IOException e) {
//Doesn't matter
}
}
//logout here
}
I tried out.flush()
before closing the stream, a longer timeout (ftpClient.setDefaultTimeout(30000)
) and even retrieveFileStream
:
InputStream is = ftpClient.retrieveFileStream(filename);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buf = new byte[10000000];
int len;
while ((len = bis.read(buf)) > 0) {
out.write(buf, 0, len);
}
if(ftpClient.completePendingCommand()) {
Log.d(TAG,"Done"); //This is always printed, even though the files aren't complete
} else {
Log.d(TAG,"Not done");
}
out.close();
bis.close();
The problem persists. I added up len
and and even ran bis.read
a couple more times (if(fullLength<singleFile[0].getSize())
) but no matter what, most of the time less than 10 bytes are missing in the downloaded file. Only rarely one of the images is actually downloaded completely but it seems to be pretty random.
How do I fix this, so it downloads all of the images completely?
来源:https://stackoverflow.com/questions/62023585/downloaded-images-are-missing-bytes