uploading large files in tornado using #stream_request_body - file-upload

#stream_request_body
class StreamHandler(RequestHandler):
def post(self):
self.temp_file.close()
def prepare(self):
max_buffer_size = 4 * 1024**3 # 4GB
self.request.connection.set_max_body_size(max_buffer_size)
self.temp_file = open("test.txt","w")
def data_received(self, chunk):
self.temp_file.write(chunk)
With the above code I am able to upload file but in raw data form as shown below
-----------------------------6552719992117258671800152707
Content-Disposition: form-data; name="dest"
csv
-----------------------------6552719992117258671800152707
Content-Disposition: form-data; name="carrier"
bandwidth
-----------------------------6552719992117258671800152707
Content-Disposition: form-data; name="file1"; filename="test.csv"
Content-Type: text/csv
And the content of uploaded file follows here.
How do I get the request parameters parsed from the file and separate the data of the file uploaded?
Is there any other way to upload large files(around 2 GB) in tornado

This is the multipart protocol used by HTML forms. Tornado can currently only parse this if it sees all the data at once, not in a streaming upload. There's a third-party library that should be able to handle this: https://github.com/siddhantgoel/streaming-form-data. See this issue for more: https://github.com/tornadoweb/tornado/issues/1842
If you control the client, it may be simpler to use a plain HTTP PUT instead of the HTML multipart form protocol. This doesn't require any special handling on the server side

Related

Accessing multiple files in a multipart request

Most of the documentation in Mule regarding multipart relates to making a request and not processing an incoming request.
I'm looking to receive multiple files in an incoming request as an array and then loop through them to upload to another service (Salesforce).
Due to the use case I'm sending two properties:
data which is metadata to create a case record
files which is an array of files to be associated with the case record
My Postman request is:
This is the payload I receive in a Mule 4 application (redacted the file data itself):
----------------------------778704367722595657997650
Content-Disposition: form-data; name="data"
Content-Type: application/json
[
{
"subject": "test
}
]
----------------------------778704367722595657997650
Content-Disposition: form-data; name="files"; filename="logo.jpeg"
Content-Type: image/jpeg
jpegdata
----------------------------778704367722595657997650
Content-Disposition: form-data; name="files"; filename="icon.png"
Content-Type: image/png
pngdata
----------------------------778704367722595657997650--
I attempt to get the files with Dataweave:
payload.parts.files
But this returns only the first file 'logo.jpeg'
I've attempted to send the files as files[] but it doesn't seem to send as an array.
It seems that I should loop through the boundary instead? If so, should my request set the boundary so it's the same each time?
Or is there a different way to access the files?
Secondarily, is multipart the correct method or should I utilize application/json instead?
The use case is to send files from a contact form in another application to Salesforce.
When DataWeave parses a multi part input it outputs an object in which each key is the name of the part. Your input has two entries with the same key name. As usual in DataWeave you should use the multi valued selector to get all the values with the same key: payload.parts.*files

How to accept any multipart file (image/pdf/csv) from postman and create the same file into SFTP location in Mule 4?

When I tried this usecase for some MIME types the content is coming in payload.parts[0].content, for some MIME types the content is coming in payload.parts.file.content. How to create the file in the same MIME type as how we received from postman in SFTP?
Quite not sure in what ways you have used and tested the both expression. Please find the screenshot below. I have added different format of datas in single request. If you use mutiple format in single request and wanting to extract individually. Use payload.parts[0].content and payload.parts[1].content
Note: This expression ideally mean whatever you add (form-data) in postman body request can be extract using index.
Example: if you have added content-type: application/xml in the below picture 3rd row, should be using payload.parts[2].content
If you're using single request payload.parts.file.content can be used.
Once after the request reached HTTP/HTTPS ( source listener), use dataweave as below to convert binary in to the defined structure data
%dw 2.0
output multipart/form-data
---
payload
After extracting the contents using the expressions, you can write in to SFTP (Screenshot) here I have stored in Vars (based on your logic)

File Upload with Additional Parameters as JSON

I am using the below code to upload image with some additional parameters.
[HttpPost]
public HttpResponseMessage Upload(Data data)
{
var count = HttpContext.Current.Request.Files.Count;
return null;
}
I tried checked this method using postman chrome extension. I passed these values
Under Headers
enctype: multipart/form-data
Content-Type: application/json
Under form-data added one image file
Under raw
{
"Id": "1",
"ModifiedBy" : "1"
}
But the problem i am getting 0 for count
The Content-Type should be multipart/form-data not application/json for your code to work. A typical content type looks like this:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvmxBBVAoH3KRsa9L
The actual post data then contains blocks of 'data' separated by the boundary. These blocks can contain a content type, but they don't have to. If you're doing file uploads the content type should not matter - the filename is what determines the type.
All that said, with WebAPI you shouldn't be using the ASP.NET HttpContext object, but rather the lower level Web API semantics. While what you're doing works as long as you run inside of the ASP.NET stack, if you self-host or maybe in the future run ontop of a different stack like OWin/Katana this code will no longer work.
To handle file uploads with Web API specific code check out this blog post from Filip W.
http://www.strathweb.com/2012/04/html5-drag-and-drop-asynchronous-multi-file-upload-with-asp-net-webapi/

Encoding Issue apending NSData to Post

I have got problem uploading a file to a server through POST
I build the request body by loading a html file and inserting the data:
------WebKitFormBoundaryMAsmIFCr12izlsoH
Content-Disposition: form-data; name="token"
%#
------WebKitFormBoundaryMAsmIFCr12izlsoH
Content-Disposition: form-data; name="userfile"; filename="%#"
Content-Type: AES256/encrypted
%#
------WebKitFormBoundaryMAsmIFCr12izlsoH--
Content-Disposition: form-data; name="submit"
Datei absenden
------WebKitFormBoundaryMAsmIFCr12izlsoH--
But to insert the the data fia string with format, it must be a string. So I alloc initWithData:data encoding NSASCIIStringEncoding cause the data can not be displayed in UTF8. The rest of the request is in UTF8, so afterwards if need dataUsingEncoding:NSUTF8StringEncoding. This breaks the data. There some bytes on the wrong place and so on. So I tried an other way, I spitted the html into two parts, and made a sandwich of it. html, data, html Unfortunately the request now looks like the second html is part of the file, so the file is broken again.
Do you know a better method?
Thanks in advance,
Jannes
I think trying to use stringWithFormat is fundamentally flawed. NSString is conceptually an array of Unicode data, but the data you are trying to put together may not be valid Unicode.
You'd be better off converting the various header portions to NSData instances and then concatenating those with the data you want to send.

Fiddler add binary file data to POST

I'm try to add binary file data directly to the request body of a POST call so I can simulate a file upload. However, I tried setting a 'before request' breakpoint and using 'insert file' but I couldn't seem to get that to work. I also tried to modify CustomRules.js to inject the file but couldn't figure out how to load binary data via JScript. Is there an easy solution here?
I'm sure this is a new feature in the year since this question was answered, but thought I'd add it anyhow:
There's a blue "[Upload file]" link in Composer now on the right side under the URL textbox. This will create a full multipart/form-data request. If you use this, you'll notice in the body you now have something that looks like this:
<#INCLUDE C:\Some\Path\my-image.jpg#>
In my case, I just wanted to POST the binary file directly with no multipart junk, so I just put the <#INCLUDE ... #> magic in the request body, and that sends the binary file as the body.
In order to send multipart/form-data, this receipe will be helped.
In upper panel (Http header), set Content-Type as below. Other values are automatically resolved.
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
And, input Response Body at the below panel as follows.
---------------------------acebdf13572468
Content-Disposition: form-data; name="description"
the_text_is_here
---------------------------acebdf13572468
Content-Disposition: form-data; name="file"; filename="123.jpg"
Content-Type: image/jpg
<#INCLUDE *C:\Users\Me\Pictures\95111c18-e969-440c-81bf-2579f29b3564.jpg*#>
---------------------------acebdf13572468--
The import rules are,
Content-Type should have two more - signs than boundary words in body.
The last of the body should be ended with two - signs.
In Fiddler script: (in Fiddler: Rules... Customize Rules), find the OnBeforeRequest function, and add a line similar to:
if (oSession.uriContains("yourdomain"))
{
oSession.LoadRequestBodyFromFile("c:\\temp\\binarycontent.dat");
}
since version 2.0, the Request Body has an "Upload File..." link that allows you to post/upload binary data.