|
1 | 1 | package io.tus.android.client; |
2 | 2 |
|
3 | 3 | import android.app.Activity; |
| 4 | +import android.content.ContentResolver; |
4 | 5 | import android.database.Cursor; |
5 | 6 | import android.net.Uri; |
| 7 | +import android.os.ParcelFileDescriptor; |
6 | 8 | import android.provider.OpenableColumns; |
| 9 | +import android.util.Log; |
7 | 10 |
|
8 | 11 | import java.io.FileNotFoundException; |
| 12 | +import java.io.IOException; |
9 | 13 | import java.util.HashMap; |
10 | 14 | import java.util.Map; |
11 | 15 |
|
12 | 16 | import io.tus.java.client.TusUpload; |
13 | 17 |
|
14 | 18 | public class TusAndroidUpload extends TusUpload { |
15 | 19 | public TusAndroidUpload(Uri uri, Activity activity) throws FileNotFoundException { |
16 | | - Cursor cursor = activity.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE, OpenableColumns.DISPLAY_NAME}, null, null, null); |
| 20 | + ContentResolver resolver = activity.getContentResolver(); |
| 21 | + Cursor cursor = resolver.query(uri, new String[]{OpenableColumns.SIZE, OpenableColumns.DISPLAY_NAME}, null, null, null); |
17 | 22 | if(cursor == null) { |
18 | 23 | throw new FileNotFoundException(); |
19 | 24 | } |
20 | 25 |
|
21 | | - int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE); |
22 | 26 | int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); |
23 | 27 | cursor.moveToFirst(); |
24 | | - long size = cursor.getLong(sizeIndex); |
25 | 28 | String name = cursor.getString(nameIndex); |
26 | 29 |
|
| 30 | + // On some files, ContentResolver#query will report the wrong filesize |
| 31 | + // even though the InputStream reads the correct length. This discrepancy |
| 32 | + // causes mismatching upload offsets when the upload should be finished. |
| 33 | + // Using the stat size from a file descriptor seems to always report the |
| 34 | + // correct filesize. |
| 35 | + // See https://github.com/tus/tus-android-client/issues/25 |
| 36 | + // See https://stackoverflow.com/questions/21882322/how-to-correctly-get-the-file-size-of-an-android-net-uri |
| 37 | + ParcelFileDescriptor fd = resolver.openFileDescriptor(uri, "r"); |
| 38 | + if(fd == null) { |
| 39 | + throw new FileNotFoundException(); |
| 40 | + } |
| 41 | + long size = fd.getStatSize(); |
| 42 | + try { |
| 43 | + fd.close(); |
| 44 | + } catch (IOException e) { |
| 45 | + Log.e("TusAndroidUpload", "unable to close ParcelFileDescriptor", e); |
| 46 | + } |
| 47 | + |
27 | 48 | setSize(size); |
28 | | - setInputStream(activity.getContentResolver().openInputStream(uri)); |
| 49 | + setInputStream(resolver.openInputStream(uri)); |
29 | 50 |
|
30 | 51 | setFingerprint(String.format("%s-%d", uri.toString(), size)); |
31 | 52 |
|
|
0 commit comments