Upload via DocumentsProvider fails if filename contains invalid characters
- Dominant language
- Kotlin
- Stars
- 5.6k
- Forks
- 2k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 92
Description
### ⚠️ Before posting ⚠️
- [x] This is a **bug**, not a question or an enhancement.
- [x] I've [searched for similar issues](https://github.com/nextcloud/android/issues) and didn't find a duplicate.
- [x] I've written a clear and descriptive title for this issue, not just "Bug" or "Crash".
- [x] I agree to follow Nextcloud's [Code of Conduct](https://nextcloud.com/contribute/code-of-conduct/).
### Steps to reproduce
1. Install https://f-droid.org/en/packages/com.nononsenseapps.feeder/
2. Click ... -> "Export feeds to OPML"
3. The DocumentsProvider opens
4. Select a location in Nextcloud
### Expected behaviour
The file should be saved and uploaded.
### Actual behaviour
The DocumentsProvider shows "Failed to save document".
### Android version
14
### Device brand and model
OnePlus 5
### Stock or custom OS?
Custom (explain in "additional information")
### Nextcloud android app version
3.30.0 (F-Droid)
### Nextcloud server version
29.0.7
### Using a reverse proxy?
Yes
### Android logs
```
10-16 13:44:31.429 4300 14761 D DocumentsStorageProvider: createDocument(), id=d88e9571089101a5c6407b061422b6a4/1
10-16 13:44:31.433 3688 4222 E MediaProvider: File name contains invalid characters
10-16 13:44:31.434 4300 14761 E DatabaseUtils: Writing exception to parcel
10-16 13:44:31.434 4300 14761 E DatabaseUtils: android.os.ParcelableException: java.io.FileNotFoundException: File could not be created
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.provider.DocumentsProvider.call(DocumentsProvider.java:1093)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.content.ContentProvider.call(ContentProvider.java:2704)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.content.ContentProvider$Transport.call(ContentProvider.java:633)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:307)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.os.Binder.execTransactInternal(Binder.java:1500)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.os.Binder.execTransact(Binder.java:1444)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: Caused by: java.io.FileNotFoundException: File could not be created
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at com.owncloud.android.providers.DocumentsStorageProvider.getFileNotFoundExceptionWithCause(DocumentsStorageProvider.java:713)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at com.owncloud.android.providers.DocumentsStorageProvider.createFile(DocumentsStorageProvider.java:583)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at com.owncloud.android.providers.DocumentsStorageProvider.createDocument(DocumentsStorageProvider.java:522)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.provider.DocumentsProvider.callUnchecked(DocumentsProvider.java:1152)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at android.provider.DocumentsProvider.call(DocumentsProvider.java:1091)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: ... 5 more
10-16 13:44:31.434 4300 14761 E DatabaseUtils: Caused by: java.io.IOException: Operation not permitted
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at java.io.UnixFileSystem.createFileExclusively0(Native Method)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:349)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at java.io.File.createNewFile(File.java:1006)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: at com.owncloud.android.providers.DocumentsStorageProvider.createFile(DocumentsStorageProvider.java:579)
10-16 13:44:31.434 4300 14761 E DatabaseUtils: ... 8 more
10-16 13:44:31.435 15745 15828 W DocumentsContract: Failed to create document
10-16 13:44:31.435 15745 15828 W DocumentsContract: android.os.ParcelableException: java.io.FileNotFoundException: File could not be created
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.ParcelableException$1.createFromParcel(ParcelableException.java:82)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.ParcelableException$1.createFromParcel(ParcelableException.java:79)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.Parcel.readParcelableInternal(Parcel.java:5016)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.Parcel.readParcelable(Parcel.java:4998)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.Parcel.createExceptionOrNull(Parcel.java:3178)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.Parcel.createException(Parcel.java:3167)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.Parcel.readException(Parcel.java:3150)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:202)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:154)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.content.ContentProviderProxy.call(ContentProviderNative.java:764)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.content.ContentProviderClient.call(ContentProviderClient.java:601)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.content.ContentResolver.call(ContentResolver.java:2456)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.provider.DocumentsContract.createDocument(DocumentsContract.java:1380)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at com.android.documentsui.DocumentsAccess$RuntimeDocumentAccess.createDocument(DocumentsAccess.java:156)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at com.android.documentsui.picker.CreatePickedDocumentTask.run(CreatePickedDocumentTask.java:79)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at com.android.documentsui.picker.CreatePickedDocumentTask.run(CreatePickedDocumentTask.java:42)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at com.android.documentsui.base.CheckedTask.doInBackground(CheckedTask.java:65)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.AsyncTask$3.call(AsyncTask.java:394)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at java.util.concurrent.FutureTask.run(FutureTask.java:264)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at com.android.documentsui.ProviderExecutor.run(ProviderExecutor.java:104)
10-16 13:44:31.435 15745 15828 W DocumentsContract: Caused by: java.io.FileNotFoundException: File could not be created
10-16 13:44:31.435 15745 15828 W DocumentsContract: at java.lang.reflect.Constructor.newInstance0(Native Method)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
10-16 13:44:31.435 15745 15828 W DocumentsContract: at android.os.ParcelableException.readFromParcel(ParcelableException.java:56)
10-16 13:44:31.435 15745 15828 W DocumentsContract: ... 20 more
10-16 13:44:31.435 15745 15828 W DocumentAccess: Failed to create document
10-16 13:44:31.435 15745 15828 W DocumentAccess: java.io.FileNotFoundException: File could not be created
10-16 13:44:31.435 15745 15828 W DocumentAccess: at java.lang.reflect.Constructor.newInstance0(Native Method)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.ParcelableException.readFromParcel(ParcelableException.java:56)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.ParcelableException$1.createFromParcel(ParcelableException.java:82)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.ParcelableException$1.createFromParcel(ParcelableException.java:79)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.Parcel.readParcelableInternal(Parcel.java:5016)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.Parcel.readParcelable(Parcel.java:4998)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.Parcel.createExceptionOrNull(Parcel.java:3178)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.Parcel.createException(Parcel.java:3167)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.Parcel.readException(Parcel.java:3150)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:202)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:154)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.content.ContentProviderProxy.call(ContentProviderNative.java:764)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.content.ContentProviderClient.call(ContentProviderClient.java:601)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.content.ContentResolver.call(ContentResolver.java:2456)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.provider.DocumentsContract.createDocument(DocumentsContract.java:1380)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at com.android.documentsui.DocumentsAccess$RuntimeDocumentAccess.createDocument(DocumentsAccess.java:156)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at com.android.documentsui.picker.CreatePickedDocumentTask.run(CreatePickedDocumentTask.java:79)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at com.android.documentsui.picker.CreatePickedDocumentTask.run(CreatePickedDocumentTask.java:42)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at com.android.documentsui.base.CheckedTask.doInBackground(CheckedTask.java:65)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at android.os.AsyncTask$3.call(AsyncTask.java:394)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at java.util.concurrent.FutureTask.run(FutureTask.java:264)
10-16 13:44:31.435 15745 15828 W DocumentAccess: at com.android.documentsui.ProviderExecutor.run(ProviderExecutor.java:104)
```
### Server error logs
_No response_
### Additional information
This is likely because the file name contains characters that Nextcloud considers invalid: `feeder-export-2024-10-16T13:54:31.855.opml`.
When first saving the file locally to the SD Card and then uploading the file to Nextcloud from within Nextcloud ( + -> Upload files), Nextcloud renames the file to `feeder-export-2024-10-16T13_54_31.855.opml`.
Nextcloud should do the same (replace invalid characters automatically) when the file is being added via the DocumentsProvider.
Contributor guide
Assessment
This issue has not been assessed yet.