fluttercommunity / flutter_uploader

background upload plugin for flutter
MIT License
210 stars 140 forks source link

Signed uploads can fail due to mime type mismatch (on Android) #244

Open JoshJuncker opened 2 years ago

JoshJuncker commented 2 years ago

Steps to Reproduce:

  1. Put a aac file in Android with a .m4a container (https://pub.dev/packages/record will produce such a file)
  2. Use mime package to determine mime type of file. Notice it returns audio/mp4
  3. Create a signed url upload request that takes headers, specifically "Content-Type" into account (like aws s3)
  4. Enqueue the upload with the signed url, path to the file, and headers that include "Content-Type": "audio/mp4" via enqueue(RawUpload( url: url, path: file.path, allowCellular: allowCellular, method: uploadMethod, headers: headers, ))
  5. Notice that the upload fails due to a signature mismatch.
  6. Digging into the Android code, String mimeType = GetMimeType(item.getPath()); in UploadWorker.java returns "audio/mpeg" instead of "audio/mp4" or just relying on the header that was passed in via enqueue. The upload request is then created with the wrong "Content-Type" header and thus fails signature validation for direct uploads (like to aws s3)

So, I think the issue is that it is likely that users will use direct upload methods that require signed urls that include content type headers. Maybe the RawUpload object could include a specific contentType parameter that is used blindly by the Android request builder if it is supplied. It could still be backwards compatible by defaulting to using the Android code to determine the mime type if contentType wasn't specified or is null. This way, you don't have to blindly sync the mime type generated on the flutter dart code side with the mime type generated in the native Android code.

I don't know if the iOS implementation does something similar or not. My guess is no since I have not run into this issue on iOS, despite the content-type header.