This is something I have been struggling to understand for a while.
The code I have been using to upload files is:
When uploading relatively small files, the upload works fine for me, mainly because:
is a small value. But any file over 12-13 MB causes memory overflow exceptions.
This means in order to upload large files I must use a (buffered) stream and not load the whole file in to a byte array.
However I struggle to use a an input stream to create the POST request, because I need to add some more form data (filename etc).
So what I do not understand is how to create a form request with both the form-data and binary file.
As you can see I am writing everything out to an OutputStream and then gettings its bytes which will give me Memory overflow errors. Alternatively, I can write the Output stream to file, but that is heavy on the sdcard. I am trying to find a way where I can direct the outputstream to the inputstream without resorting to the intermediate.
If this doesnt work, then I will need to find an alternative way to upload files maybe by wrapping the Http Multipart Request object?
The code I have been using to upload files is:
B4X:
Sub PrepareFileToUpload (link As String, Dir As String, FileName As String) As HttpRequest
Dim req As HttpRequest
req.InitializePost2(HttpUtils.EncodeUrl(link), ("file=" & HttpUtils.EncodeUrl(FileName)).GetBytes("UTF8"))
req.SetContentType("application/x-www-form-urlencoded")
OAuth.Sign(req)
Dim authHeader As String
authHeader = OAuth.GetAuthorizationHeaderValue(req)
'write the file
Dim stream As OutputStream
Dim size_i As Int
stream.InitializeToBytesArray(20)
Dim EOL As String
EOL = Chr(13) & Chr(10) 'CRLF constant matches Android end of line character which is chr(10).
Dim b() As Byte
b = ("--" & boundary & EOL & "Content-Disposition: form-data; name=" _
& QUOTE & "file" & QUOTE & "; filename=" & QUOTE & FileName & QUOTE _
& EOL & "Content-Type: " & "application/octet-stream" & EOL & _
"Content-Transfer-Encoding: binary" & EOL & EOL).GetBytes("UTF8")
stream.WriteBytes(b, 0, b.Length)
Dim in As InputStream
in = File.OpenInput(Dir, FileName)
File.Copy2(in, stream) 'read the file and write it to the stream
b = EOL.GetBytes("UTF8")
stream.WriteBytes(b, 0, b.Length)
b = (EOL & "--" & boundary & "--" & EOL).GetBytes("UTF8")
stream.WriteBytes(b, 0, b.Length)
b = stream.ToBytesArray
Dim in As InputStream
in.InitializeFromBytesArray(b,0,b.Length)
UploadLength = in.BytesAvailable
PostInputStream.Initialize(in)
Dim req As HttpRequest
'req.InitializePost2(link, b)
req.InitializePost(HttpUtils.EncodeUrl(link), PostInputStream,b.Length)
req.SetContentType("multipart/form-data; boundary=" & boundary)
req.SetContentEncoding("UTF8")
req.SetHeader("Authorization", authHeader)
Return req
End Sub
When uploading relatively small files, the upload works fine for me, mainly because:
B4X:
b = stream.ToBytesArray
This means in order to upload large files I must use a (buffered) stream and not load the whole file in to a byte array.
However I struggle to use a an input stream to create the POST request, because I need to add some more form data (filename etc).
So what I do not understand is how to create a form request with both the form-data and binary file.
As you can see I am writing everything out to an OutputStream and then gettings its bytes which will give me Memory overflow errors. Alternatively, I can write the Output stream to file, but that is heavy on the sdcard. I am trying to find a way where I can direct the outputstream to the inputstream without resorting to the intermediate.
If this doesnt work, then I will need to find an alternative way to upload files maybe by wrapping the Http Multipart Request object?