react-native-fs icon indicating copy to clipboard operation
react-native-fs copied to clipboard

Chunked upload has extra CR/LF mark and file is corrupted in Android

Open tero-paananen opened this issue 2 years ago • 8 comments

I upload one file chunk at the time using Uploader.java. When chunks are combined in the server into one file there is extra CR/LF = 0d0a = \r\n mark in end of each chunk and combined file is corrupted.

tero-paananen avatar Feb 07 '22 05:02 tero-paananen

Issue is here where final end boundary adds extra \r\n marks before boundary.

https://github.com/itinance/react-native-fs/blob/01952b46f27d133ebad382b7fb5053a44d9de7c8/android/src/main/java/com/rnfs/Uploader.java#L173

Solution is to remove crlf \r\n from begining of final boundary tail:

https://github.com/itinance/react-native-fs/blob/01952b46f27d133ebad382b7fb5053a44d9de7c8/android/src/main/java/com/rnfs/Uploader.java#L56

POST /test HTTP/1.1
Host: foo.example
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"

value2
--boundary--

See more https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST

tero-paananen avatar Feb 07 '22 07:02 tero-paananen

I updated also getting string length into bytes: https://github.com/itinance/react-native-fs/blob/01952b46f27d133ebad382b7fb5053a44d9de7c8/android/src/main/java/com/rnfs/Uploader.java#L110

into totalFileLength += tail.getBytes().length;

tero-paananen avatar Feb 07 '22 07:02 tero-paananen

Any thoughts?

tero-paananen avatar Feb 07 '22 07:02 tero-paananen

Currently my patch is like this react-native-fs+2.16.6.patch that does not fit version in master currently but fix can be seen very well here.

diff --git a/node_modules/react-native-fs/android/src/main/java/com/rnfs/Uploader.java b/node_modules/react-native-fs/android/src/main/java/com/rnfs/Uploader.java
index 5324a36..e0a63bc 100644
--- a/node_modules/react-native-fs/android/src/main/java/com/rnfs/Uploader.java
+++ b/node_modules/react-native-fs/android/src/main/java/com/rnfs/Uploader.java
@@ -50,7 +50,7 @@ public class Uploader extends AsyncTask<UploadParams, int[], UploadResult> {
         String crlf = "\r\n";
         String twoHyphens = "--";
         String boundary = "*****";
-        String tail = crlf + twoHyphens + boundary + twoHyphens + crlf;
+        String tail = twoHyphens + boundary + twoHyphens + crlf;
         String metaData = "", stringData = "";
         String[] fileHeader;
         int statusCode, byteSentTotal;
@@ -104,7 +104,7 @@ public class Uploader extends AsyncTask<UploadParams, int[], UploadResult> {
                             "Content-Type: " + filetype + crlf;
                     ;
                     if (files.length - 1 == fileCount){
-                        totalFileLength += tail.length();
+                        totalFileLength += tail.getBytes().length;
                     }
 
                     String fileLengthHeader = "Content-length: " + fileLength + crlf;
@@ -119,9 +119,9 @@ public class Uploader extends AsyncTask<UploadParams, int[], UploadResult> {
             }
             if (!binaryStreamOnly) {
                 long requestLength = totalFileLength;
-                requestLength += stringData.length() + files.length * crlf.length();
+                requestLength += stringData.getBytes().length + files.length * crlf.getBytes().length;
                 connection.setRequestProperty("Content-length", "" +(int) requestLength);
-                connection.setFixedLengthStreamingMode((int)requestLength);
+                connection.setFixedLengthStreamingMode(requestLength);
             }
             connection.connect();
 

tero-paananen avatar Feb 07 '22 10:02 tero-paananen

This open PR that fixes boundary seems to be quite important https://github.com/itinance/react-native-fs/pull/1004

tero-paananen avatar Feb 07 '22 17:02 tero-paananen

Any plans on merging those fixes to main branch? Quite important one to fix the entire Upload procedure on Android.

punov avatar Sep 05 '22 12:09 punov

@tero-paananen What didn't work for me with your patch is that I still have the extra CR:LF at the end of file, that breaks the signature validation if you care about particular byte-to-byte size comparison. Why did they even need to add those extra CR:LF everywhere?

punov avatar Sep 05 '22 15:09 punov

I tried to check that this should be according to spec https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST

This works for us. Make your proposition? Only final CR:CL is bug here?

tero-paananen avatar Sep 05 '22 17:09 tero-paananen