0-byte files not detected when downloading files on Android

I have an Android app that downloads hundreds of files from the Internet. After downloading, some files turn out to be 0-bytes. The application tries to detect such cases and delete such files after downloading, but sometimes it fails. The problem is more common on Android 4.x devices.

Here is the method that performs the download. I get the number of bytes actually read from inputStream.read(buffer) .

 public class Utils { public static class DownloadFileData { int nTotalSize; int nDownloadedSize; } public interface ProgressCallback { void onProgress(long nCurrent, long nMax); } public static boolean downloadFile(String sFileURL, File whereToSave, DownloadFileData fileData, ProgressCallback progressCallback) { InputStream inputStream = null; FileOutputStream fileOutput = null; try { URL url = new URL(sFileURL); URLConnection connection = url.openConnection(); //set up some things on the connection connection.setDoOutput(true); connection.connect(); fileOutput = new FileOutputStream(whereToSave); inputStream = connection.getInputStream(); fileData.nTotalSize = connection.getContentLength(); fileData.nDownloadedSize = 0; byte[] buffer = new byte[1024]; int bufferLength = 0; //used to store a temporary size of the buffer // now, read through the input buffer and write the contents to the file while ((bufferLength = inputStream.read(buffer)) > 0) { // if interrupted, don't download the file further and return // also restore the interrupted flag so that the caller stopped also if (Thread.interrupted()) { Thread.currentThread().interrupt(); return false; } // add the data in the buffer to the file in the file output stream fileOutput.write(buffer, 0, bufferLength); // add up the size so we know how much is downloaded fileData.nDownloadedSize += bufferLength; if (null != progressCallback && fileData.nTotalSize > 0) { progressCallback.onProgress(fileData.nDownloadedSize, fileData.nTotalSize); } } return true; } catch (FileNotFoundException e) { return false; // swallow a 404 } catch (IOException e) { return false; // swallow a 404 } catch (Throwable e) { return false; } finally { // in any case close input and output streams if (null != inputStream) { try { inputStream.close(); inputStream = null; } catch (Exception e) { } } if (null != fileOutput) { try { fileOutput.close(); fileOutput = null; } catch (Exception e) { } } } } 

Here is a piece of code that handles downloads. Since sometimes the number of bytes read is incorrect (this is> 0, and the real file is 0 bytes in size), I check the size of the downloaded file using outputFile.length() . But this again gives a value> 0, although the file is really 0 bytes. I also tried to simply create a new file and read its size using recheckSizeFile.length() . However, the size is defined as> 0, while it is really 0 bytes.

 Utils.DownloadFileData fileData = new Utils.DownloadFileData(); boolean bDownloadedSuccessully = Utils.downloadFile(app.sCurrenltyDownloadedFile, outputFile, fileData, new Utils.ProgressCallback() { ... // progress bar is updated here }); if (bDownloadedSuccessully) { boolean bIsGarbage = false; File recheckSizeFile = new File(sFullPath); long nDownloadedFileSize = Math.min(recheckSizeFile.length(), Math.min(outputFile.length(), fileData.nDownloadedSize)); // if the file is 0bytes, it garbage if (0 == nDownloadedFileSize) { bIsGarbage = true; } // if this is a video and if of suspiciously small size, it's // garbage, too else if (Utils.isStringEndingWith(app.sCurrenltyDownloadedFile, App.VIDEO_FILE_EXTENSIONS) && nDownloadedFileSize < Constants.MIN_NON_GARBAGE_VIDEO_FILE_SIZE) { bIsGarbage = true; } if (bIsGarbage) { ++app.nFilesGarbage; app.updateLastMessageInDownloadLog("File is fake, deleting: " + app.sCurrenltyDownloadedFile); // delete the garbage file if (null != outputFile) { if (!outputFile.delete()) { Log.e("MyService", "Failed to delete garbage file " + app.sCurrenltyDownloadedFile); } } } else { ... // process the normally downloaded file } 

I'm not sure, but I think there is an error in Android with the file size to read. Has anyone seen a similar problem? Or am I maybe something is wrong here? Thanks!

EDIT: how do I determine that files are 0-byte: all files that are downloaded go through the procedures described. When I then look at the download folder with a file browser (Ghost Commander), some of the files (for example, 10%) will be 0-byte. They cannot be played by the video player (displayed as a β€œbroken file” icon).

+4
source share
2 answers

It seems to me that your problem is that you only check garbage files if calling Utils.downloadFile returns true. If the download fails in the getInputStream call or the first read , you will create a file with a zero length that will never be deleted.

+1
source

You must call flush () on the FileOutputStream file to ensure that all data is written to the file. This should make your problem with 0-byte files less common.

To check for 0 byte files using File.length (), you need to work correctly. You can open the shell (adb shell) on the device and run ls -l to count the number of bytes displayed on it is 0 (maybe your file manager has some strange problems). Also, please debug (or put some log statements) that sFullPath contains the correct file paths. I do not see where sFullPath is installed in your code above and why you are not just using outputFile, but recreating another File object.

+1
source

Source: https://habr.com/ru/post/1489042/


All Articles