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 :)
Related
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"
I want to return a TSV file from a web call in Hunchentoot (SBCL), but want the user to just save the raw result blatted to the page, rather than use a separate file and download link (which is hard because of local firewall complexities).
I can't figure out how to output the page without any headers at all, i.e., to make it just plain raw text. (I know that the browser would make a mess w/o headers in the DOM, but don't care; the goal is just to have the user save the page, not read it.)
I've tried various combinations of
(setf (hunchentoot:content-type*) "text/plain")
and
(cl-who:with-html-output-to-string
(*standard-output* nil :prologue nil)
and setting the content-type* inside, outside, and around the with... but I always get header junk.
Writing a string directly
I tried defining a handler as follows:
(define-easy-handler (text :uri "/text") ()
(setf (content-type*) "text/csv")
"a,b,c")
When I visit the page locally, the browser automatically downloads a text file without even displaying (this is probably a setting we can change in Chrome, I don't know).
When I enable the browser developer mode, here are the response headers I receive as part of the HTTP protocol:
HTTP/1.1 200 OK
Server: ...
Date: ...
Content-Type: text/csv; charset=utf-8
Content-Length: 5
Connection: keep-alive
But the file itself is just the string a,b,c.
If I change the content-type to "text/plain", then the browser successfully displays the text, and nothing else (the HTTP headers are the same).
Remarks
You don't need to use the cl-who macros if you do not intend to build an HTML document, in fact its better not to. In any case, you can supply your own REPLY-CLASS when initializing the acceptor (see https://edicl.github.io/hunchentoot/#replies) and have a very low-level control about what you emit as a reply, headers included. But I don't think this is necessary in your case. I don't clearly understand where your problem comes from, but sending back a plain text is something the framework is supposed to be able to do out of the box. Please add more details if you can.
Is the correct answer not to use the Content-Disposition header?
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
I'm trying to understand the http request, when I send a string of data using the post method on the request body there is a value that we send as below:
--------------------------d74496d66958873e
Content-Disposition: form-data; name="person"
anonymous
--------------------------d74496d66958873e
but if we send a file using post method it will be like this:
--------------------------d74496d66958873e
Content-Disposition: form-data; name="fileToUpload"; filename="icon.png"
Content-Type: image/png
-O9†q#ë#ÞÿËà3l†v}uá#t(<‡c3f
úS©59ñõCáa#Ž¡#Za%ð.ž zxý˜F#ZqÄð&^
jx[1…ÕЊËÂ$Æ‚#Þ
--------------------------d74496d66958873e
my question is:
what is the foreign character contained between -------------------------- d74496d66958873e when we send the file?
i mean
-O9†q#ë#ÞÿËà3l†v}uá#t(<‡c3f
úS©59ñõCáa#Ž¡#Za%ð.ž zxý˜F#ZqÄð&^
jx[1…ÕЊËÂ$Æ‚#Þ
whether the character is a binary, hexa, or base64 or what?
how to change image file to the character when we want to write http request manually using programming language?
Those are plain binary bytes. All the bytes that the file icon.png contained when it was sent by the HTTP client.
The format is described in RFC 1867 and basically works like this:
--[boundary]
[headers]
[N bytes]
--[boundary]
[headers]
[M bytes]
--[boundary]--
To extract the contents, you'll need to parse past the boundary, parse the headers (0, 1 or many) and then read the binary data until you reach the ending boundary. (The final boundary has two extra dashes on the right.)
... and there can be any amount of such parts, in a single multipart POST.
After importing an entity (e.g. Car) from JDL studio with one field as a Blob I notice that the generated code looks like this:
this.dataUtils.toBase64(file, (base64Data) => {
car[field] = base64Data;
car[`${field}ContentType`] = file.type;
});
i.e. the file is base64 encoded and subsequently sent with content-type:application/json.
From this post, it seems that the canonical way to upload files to a REST API is using the multipart/form-data (as per W3 recommendation).
For my curiosity, I'm just wondering why base64 / application/json was used as opposed to multipart/form-data.
Thanks,