FileUploaderPlugin - MultiPartDataMediaFormatterBoundary error on Android - xamarin.forms

I am getting an error when trying to upload files to android using the FileUploaderPlugin, even one file doesn't work.
When using the Upload method I am using the option which takes an array of FileBytesItem to pass through multiple byte arrays.This works nicely on iOS but fails on Android. I am assuming this is a header issue with OkHttp
I get the information below in the Error handler
MultiPartDataMediaFormatterBoundary1q2w3e
Content-Disposition: form-data; name ="[0].Key"
MultiPartDataMediaFormatterBoundary1q2w3e
Content-Disposition: form-data; name ="[0].Value"
An error has occurred
Content-Type : "multipart/form-data"
StatusCode: 500
I have tried adding options like a boundary string with the '-' characters and a unique id and also by specifying the Content-Type & Content-Disposition directly but to no avail.
Any help would be appreciated

Figured it out, I was passing a dynamic value to the field name in FileBytesItem and it seems to fail on Android with a 500 error if it has slash character(s) in it. This doesn't seems to cause an issue on iOS

Related

How to distinguish between mutli-part form data of empty file and missing file?

I try on server side to distinguish between the upload of empty file and not-uploaded file
The POST body content of an empty file is:
------WebKitFormBoundaryAYxCGhPMYcmdkdlv
Content-Disposition: form-data; name="_1"
dd
------WebKitFormBoundaryAYxCGhPMYcmdkdlv
Content-Disposition: form-data; name="_2"; filename="foo"
Content-Type: application/octet-stream
------WebKitFormBoundaryAYxCGhPMYcmdkdlv
Content-Disposition: form-data; name="_3"
Upload
------WebKitFormBoundaryAYxCGhPMYcmdkdlv--
While missing file is
------WebKitFormBoundaryMldAHhbBqWpKPlRY
Content-Disposition: form-data; name="_1"
dd
------WebKitFormBoundaryMldAHhbBqWpKPlRY
Content-Disposition: form-data; name="_2"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryMldAHhbBqWpKPlRY
Content-Disposition: form-data; name="_3"
Upload
------WebKitFormBoundaryMldAHhbBqWpKPlRY--
The only difference is filename= content one is empty other contains the file name (same behavior for Firefox and Chromium)
Questions:
Are there any conditions that browser wouldn't provide a filename (security or something like that)?
Is it actually valid/standard way to distinguish between empty file and non-set file, please provide reference.
Is Content-Type: application/octet-stream is standard response and it will be set in case of non-uploaded file?
I'd like to see some references to standards that confirm or disprove my observations
1. Filename
The original specification for "Form-based File Upload in HTML" was RFC1867
According to that specification, the filename parameter
"is not required, but is strongly recommended in any case where the original filename is known"
This spec was superceded by RFC2388 - "Returning Values from Forms: multipart/form-data", which states
The sending application MAY supply a file name ... as specified in RFC2184;
(where RFC2184 goes on to stress its importance, without requiring it)
Note that it refers to "the sending application". The spec makes it clear that it is application agnostic.
For a cross-browser view on actual implementation however, Mozilla's MDN documentation for FormData sheds some light on it.
In the context of FormData.append() where a file/blob is set but filename is not set explicitly:
The default filename for Blob objects is "blob". The default filename for File objects is the file's filename.
2. Difference between empty & no file
To answer this, it's important to note Section 5.7 of RFC2388 - "Correlating form data with the original form"
This specification provides no specific mechanism by which
multipart/form-data can be associated with the form that caused it to
be transmitted. This separation is intentional...
This is answered in the HTML5 specification however, which details how form data is constructed.
...if the field element is an <input> element whose type attribute is in the File Upload state, then for each file selected in the <input> element, append an entry to the form data set with the name as the name, the file (consisting of the name, the type, and the body) as the value, and type as the type. If there are no selected files, then append an entry to the form data set with the name as the name, the empty string as the value, and application/octet-stream as the type.
This matches your observation above.
Looking to how a real-world server implementation deals with this, take the PHP runtime as an example.
Its API makes no distinction between "no file" and "empty file" - and will raise a single error UPLOAD_ERR_NO_FILE in either case.
As PHP is open source (written in C), you can see that implementation here
3. MIME content-type encoding
This is answered in #2 above - As detailed in the HTML5 spec, (from a compliant browser) it will always be application/octet-stream where the form value is empty.
For completeness, if a file is provided, RFC2388 specifies that:
If the contents of a file are returned via filling out a form, then the file input is identified as the appropriate media type, if known, or "application/octet-stream"

Jmeter 2.9 HTTP Sampler for PUT not passing parameters

I'm using Jmeter version 2.9, HTTP sampler to test my rest services.
The GET and POST are working without any issues, where as PUT is not passing any parameters in the request to the server.
I verified it with view results in tree.
Any reasons on why this is happening and work around this issue?
It worked for me. Based on what I read on internet, there were different solutions suggested:
Changing Content-Encoding to UTF-8
Pass the PUT parameters in the "body data" tab (as opposed to passing them in tabular format in the "Parameters" tab)
Setting Content-Type header to application/json in the HTTP Header Manager
Passing the parameters via a file (even if this were to work, how would you pass dynamic values?)
passing it as POST with a combination of above points.
WHAT WORKED FOR ME is this combination: Set content type to application/json + Pass parameters as "JSON" in the **body data tab (below is an example)
I did not need to specify UTF-8 or anything else.
EXAMPLE JSON PARAMETER BODY:
{"title":"JMeterTitle","preMortar":"JMeterPre","postMortar":"JMeterPost"}
Pass parameters in path field using:
?name=value&name2=value2
and body in Raw Post body.
if it doesn't work report a bug .
Example:
I am using JMeter 2.11 and I had the same problem. I solved in this way:
1) Setting Content-Type header similar to that you are using in your api method(Example: application/json or application/x-www-form-urlencoded etc.) in the HTTP Header Manager.
2)In HTTP Request. Body Data should look like this:
KEY=VALUE&KEY=VLAUE&KEY=VLAUE&KEY=VLAUE.......
First, try see the logs.
Had a similar problem.
I was using wrongly the "Content-enconding" field as it were the HTTP
Content-Type param. They are not related.
If you need to set Content-Type=application/json you have to use a "HTTP Header Manager" config element.
After setting correctly Content-enconding to UTF-8 the put request started to work.
You should add a parameter with an empty name (in the "parameters" tab).
If the problem persists use the result tree view to analyze the request settings.
I'm using JMeter 2.13 and facing with similar problem. This is How I've solved it:
Setting Content-Type header to text/plain in the HTTP Header Manager
Changing Content-Encoding to UTF-8
In the parameters tab, add the params without name and separated with ampersand character (&)
Screenshot JMeter PUT request example
Hope it helps!

cfhttp returns 415 Unsupported Media Type on CF9

The following code is working fine on CF10.
httpSvc = New http();
httpSvc.setMethod("post");
httpSvc.setCharset("utf-8");
httpSvc.setUrl(svcLocation);
httpSvc.setClientCert(certLocation);
httpSvc.setClientCertPassword(certPassword);
httpSvc.addParam(type="body", name="body",value=requestParameters);
result = httpSvc.send().getPrefix();
The value of requestParameters is:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:processCreditCard xmlns:ns2="urn:com.qvalent.payway.api">
<requestParameters>customer.orderNumber=5396&card.CVN=070&order.amount=101&customer.merchant=xxxx&card.expiryMonth=08&card.expiryYear=20&order.ECI=SSL&card.PAN=0000000000000008&card.currency=AUD&customer.username=xxxxxx&order.type=capture&customer.password=xxxxxxx</requestParameters>
</ns2:processCreditCard>
</S:Body>
</S:Envelope>
However, when I place it on a CF9 server, the response FileContent is empty and I get the following status code:
415 Unsupported Media Type
Here is a link displaying the full response: http://www.onoffezy.com/_testing/gateway/
Trawling Google, a 415 status code states that the mime type requested by the client is not available on the server. However I could not find anywhere that the mime type can be set for request. Is there a difference int he default mimetype between cf9 and cf10?
I have looked closely at the documentation for both versions, but cannot find a difference that may explain this.
If anyone can shed some light on this and let me know what I need to do differently on CF9 would be hugely appreciated.
Many Thanks
Thanks to all that helped. I found the problem.
httpSvc.addParam(type="body", name="body",value=requestParameters);
needed to be changed to:
httpSvc.addParam(type="xml", name="body",value=requestParameters);
It appears that cf9 sends type='body' through as Binary, but cf10 sends it as a string, or works out it is xml and handles it as such. Once I changed the type to 'xml', cf9 started sending it through as a string of xml, and not binary.
While I can't say for certain this will solve your problem, have you tried setting the 'Accept' request header to the content type of the response?
For example:
acceptType = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
httpSvc.addParam(name="Accept", value=acceptType, type="header");
According to the documentation here the type="body" specifies the body of the HTTP request. ColdFusion does not automatically set a content-type header or URL encode the body contents. To specify the content-type, use a separate cfhttpparam tag with type=header. So maybe it will help to specify this header for your request.
Something like:
httpSvc.addParam(type="header", name="Content-Type", value="application/x-www-form-urlencoded");
You did not supply an example of your body content. You may have to play around with the value for your specific content type. Here is a list of the available MIME types.
You have misspelled the word parameters in the variable requestParamaters from your example. What is the value of it?

ASP.Net not populating Request.Files on receiving multipart data

I'm sending files from an android app to a asp.net webform using multipart/form-data as the content type. However the Request.files property does not get populated. Reading the Request object I get the following
Request.Params("ALL_HTTP")
"HTTP_CONNECTION:Keep-Alive HTTP_CONTENT_LENGTH:8913 HTTP_CONTENT_TYPE:multipart/form-data;boundary=*********************** HTTP_HOST:192.168.1.2 HTTP_USER_AGENT:Dalvik/1.2.0 (Linux; U; Android 2.2; sdk Build/FRF91) "
The HTTP_CONTENT_LENGTH shows the correct length. I guess I will have to do a binary read and then parse the content and store the file contents. Has anyone done this before or is there a library/class available?
Thanks
How are you writing the files to the request stream? The following rules should be followed when programatically uploading files (binary streams):
1) Write a boundary (it could be anything prefixed by two dashes). Here is an example boundary:
private string boundary = "----" + DateTime.Now.Ticks;
2) Write content disposition in the form:
Content-Disposition: form-data; name="{name}"; filename="{filename}"
3) Write the content type
4) Write an empty line
5) Write the bytes to the request stream
6) Write the end boundary, it marks the end of the request. It should be in the following form:
"--" + boundary + "--"
7) Write an empty line and flush (if needed) the request.
Here is how sample upload request should look inside an Http debugging tool like fiddler:
------634388181001966332
Content-Disposition: form-data; name="files"; filename="cald_3d.JPG"
Content-Type: application/octet-stream
1010101001... (more bytes)
------634388181001966332--
Then, on the server, access the file with Request.Files[name], the same name which you have used when specifying Content Disposition. Good luck :)

multipart/form-data, what is the default charset for fields?

what is the default encoding one should use to decode multipart/form-data if no charset is given? RFC2388 states:
4.5 Charset of text in form data
Each part of a multipart/form-data is supposed to have a content-
type. In the case where a field element is text, the charset
parameter for the text indicates the character encoding used.
For example, a form with a text field in which a user typed 'Joe owes
<eu>100' where <eu> is the Euro symbol might have form data returned
as:
--AaB03x
content-disposition: form-data; name="field1"
content-type: text/plain;charset=windows-1250
content-transfer-encoding: quoted-printable>>
Joe owes =80100.
--AaB03x
In my case, the charset isn't set and I don't know how to decode the data within that text/plain section. As I do not want to enforce something that isn't standard behavior I'm asking what the expected behavior in this case is. The RFC does not seem to explain this so I'm kinda lost.
Thank you!
This apparently has changed in HTML5 (see http://dev.w3.org/html5/spec-preview/constraints.html#multipart-form-data).
The parts of the generated multipart/form-data resource that correspond to non-file fields must not have a Content-Type header specified.
So where is the character set specified? As far as I can tell from the encoding algorithm, the only place is within a form data set entry named _charset_.
If your form does not have a hidden input named _charset_, what happens? I've tested this in Chrome 28, sending a form encoded in UTF-8 and one in ISO-8859-1 and inspecting the sent headers and payload, and I don't see charset given anywhere (even though the text encoding definitely changes). If I include an empty _charset_ field in the form, Chrome populates that with the correct charset type. I guess any server-side code must look for that _charset_ field to figure it out?
I ran into this problem while writing a Chrome extension that uses XMLHttpRequest.send of a FormData object, which always gets encoded in UTF-8 no matter what the source document encoding is.
Let the request entity body be the result of running the multipart/form-data encoding algorithm with data as form data set and with utf-8 as the explicit character encoding.
Let mime type be the concatenation of "multipart/form-data;", a U+0020 SPACE character, "boundary=", and the multipart/form-data boundary string generated by the multipart/form-data encoding algorithm.
As I found earlier, charset=utf-8 is not specified anywhere in the POST request, unless you include an empty _charset_ field in the form, which in this case will automatically get populated with "utf-8".
This is my understanding of the state of things. I welcome any corrections to my assumptions!
The default charset for HTTP 1.1 is ISO-8859-1 (Latin1), I would guess that this also applies here.
3.7.1 Canonicalization and Text Defaults
--snip--
The "charset" parameter is used with some media types to define the character set (section 3.4) of the data. When no explicit charset parameter is provided by the sender, media subtypes of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP. Data in character sets other than "ISO-8859-1" or its subsets MUST be labeled with an appropriate charset value. See section 3.4.1 for compatibility problems.
Thanks to the detailed explanation by #owlman.
Just some more info here:
Upload request payload fragment:
------WebKitFormBoundarydZAwJIasnBbGaUqM
Content-Disposition: form-data; name="file"; filename="xxx.txt"
Content-Type: text/plain
If "xxx.txt" has some UNICODE char in it using UTF-8 encoding, Resin(as of 4.0.40) can't decode it correctly, but Jetty(9.x) can.
I think the reason for Resin's behavior is that the Content-type doesn't specify any encoding, so Resin decode file name using "ISO8859-1", which may result in garbled characters.
I did some googling:
https://mail-archives.apache.org/mod_mbox/struts-user/200310.mbox/%3C3FA0395B.1080209#kumachan.net.nz%3E
It seems that Resin's behavior is according to Servlet Spec 2.3
And I can't find any settings from http://www.caucho.com/resin-4.0/reference.xtp
which can change this behavior for Resin.

Resources