Simluate a file upload POST request via Postman - post

I'm developing a file upload method and I wanna test it independently of a frontend interface.
Normally I would use an HTML form to send a file using the 'Content-Type': 'multipart/form-data' headers.
Now as I get it, the files are converted to base64 and sent as strings.
I'm using this tool to convert a file to base64, but with both multipart or form-data headers Postman gives me this error:
431 Request Header Fields Too Large
What am I missing?

You don't need to encode the file yourself, you need to use form-data, change key type from text to file and select the file as below:

Related

How to return a pdf file from a rest api?

I have setup a rest API inside a ruby on rails application, I now have a requirement to generate a PDF and return this PDF from a get request. I am looking for some advice on how to implement this feature.
Some of the requirements that I have are as follows: I can't save the file and give the end user a link to the file because the data in the file can be updated at any time. I am using the application as microservice so there isn't a front end that I can use to display the file.
So here is my thinking I would love some advice on how to implement this feature.
I would like to make a get request to a specific endpoint in the application. I expect a PDF file to be returned which I can then display to the end user.
I am currently using WickedPdf gem to generate a temporary PDF file, but I am really struggling with how the response should look.
Any advice would be much appreciated.
One way is to create a PDF file in memory and stream it to the client. I prefer this way, maybe later you will have to send PDF files via email, or just save them to some backup disk etc...
def get_pdf
pdf = WickedPdf.new.pdf_from_string('<h1>Hello There!</h1>')
send_data pdf, filename: 'file_name.pdf'
end
You can put the PDF generation to a different service and just call it in the controller. This provides isolation and you can test it separately.
Also you can debug the endpoint response with HTTPie http get http://localhost:3000/invoices/1/get_pdf
Rails will set all the necessary HTTP response headers:
Content-Disposition: attachment; filename="file_name.pdf"
Content-Length: 5995
Content-Transfer-Encoding: binary
Content-Type: application/pdf
So when the user clicks on a link that points to the endpoint, most probably the download dialog will pop up because of the Content-Disposition: attachment; header
Other solution is to render the get_pdf.html as PDF and send back to the client:
def get_pdf
render pdf: "file_name"
end
But in this case the Content-Disposition header will be inline, which means the browser will open the pdf (if it can read PDF format) instead of offering to download it.
Upload pdf to Amazon s3 and generate link then get pdf link in apis.
I don't know if you still need this, but for anyone in the future I found a nice solution:
pdf = WickedPdf.new.pdf_from_string(render_to_string "entradas/entradaspdf.pdf.erb")
send_data pdf, filename: "bergha.pdf", disposition: "inline"
I'm loading my pdf-html-view based template through "render_to_string" ruby method which returns the view contents in string. Then WickedPdf converts it to a pdf binary, and finally save that to "pdf" var.
Finally instead of "render" I use the "send_data" method, where first parameter is the output data (my pdf var), second is the filename of the output data, and third (optional) is to change Content-Disposition header to tell browser whether to load the file (inline) or just download it (attachment).
Hope it works, it does just fine for me

Rails Post multipart form with JSON and file

I am making a POST request from my Ruby on Rails controller to an API. The API needs to receive a multipart form where one part is JSON and the other part is a file.
Here's my best stab at it so far:
Api::Document.post("document_versions",
user_id: params[:user_id].to_i,
client_token: params[:client_token],
file_name: params[:file_name],
doc_name: params[:doc_name],
doc_type_id: params[:doc_type_id].to_i,
file: params[:upload].tempfile,
"Content-type" => "multipart/form-data; boundary= SomethingToSeparateParts")
On the API side, it receives
{"method":"POST","auth_token":"12345","timestamp":"2015-05-26T20:18:16Z","status_code":500,"request_url":"/v1/document_versions","duration":"3.902005ms","user_agent":"Faraday v0.9.0","request_body":"{\"user_id\":138,\"client_token\":\"12345\",\"file_name\":\"benTest.png\",\"doc_name\":\"BENTEST\",\"doc_type_id\":1,\"file\":[\"�PNG\\r\\n\",\"\\u001A\\n\",\"\\u00
...
0000\\u0000IEND�B`�\"],\"Content-type\":\"multipart/form-data; boundary= SomethingToSeparateParts\"}"}
So I think I have it coming as multipart/form-data, but it only has one part -- the JSON containing all attributes, including the file. I would like the JSON to contain everything BUT the file, and the file to be separated to another part of the multipart, separated by the boundary. How can I do this?

Download a file with URLDownloadToFile

I use URLDownloadToFile to download a file in Delphi. In the url there is not the real name of the file. Is it possible to specify just the path of the file, keeping the default name that i.e. Explorer show?
You are in a catch-22 situation. You need to give URLDownloadToFile() a filename, but you have to request the URL first to discover if it has its own filename.
You have two choices:
Send a separate HEAD request to the URL first and check the Content-Disposition response header, if present. You can use HttpSendRequest() and HttpQueryInfo() for that, or any other HTTP library. You can then format a filename as needed, and then download the URL to that filename.
Use a temp filename for the download, then check the Content-Disposition response header, if present, and rename the file if needed. To get the response headers from URLDownloadToFile() you have to write a class that implements the IBindStatusCallback and IHttpNegotiate COM interfaces, then pass an instance of that class to the lpfnCB parameter. The response headers will be passed to your IHttpNegotiate.OnResponse() implementation.

How to validate a file as image on the server before uploading to S3?

The flow is:
The user selects an image on the client.
Only filename, content-type and size are sent to the server. (E.g. "file.png", "image/png", "123123")
The response are fields and policies for upload directly to S3. (E.g. "key: xxx, "alc": ...)
The case is that if I change the extension of "file.pdf" to "file.png" and then uploads it, the data sent to the server before uploads to S3 are:
"file.png"
"image/png"
The servers says "ok" and return the S3 fields for upload .
But the content type sent is not a real content type. But how I can validate this on the server?
Thanks!
Example:
Testing Redactorjs server side code (https://github.com/dybskiy/redactor-js/blob/master/demo/scripts/image_upload.php) it checks the file content type. But trying upload fake image (test here: http://imperavi.com/redactor/), it not allows the fake image. Like I want!
But how it's possible? Look at the request params: (It sends as image/jpeg, that should be valid)
When I was dealing with this question at work I found a solution using Mechanize.
Say you have an image url, url = "http://my.image.com"
Then you can use img = Mechanize.new.get(url)[:body]
The way to test whether img is really an image is by issuing the following test:
img.is_a?(Mechanize::Image)
If the image is not legitimate, this will return false.
There may be a way to load the image from file instead of URL, I am not sure, but I recommend looking at the mechanize docs to check.
With older browsers there's nothing you can do, since there is no way for you to access the file contents or any metadata beyond its name.
With the HTML5 file api you can do better. For example,
document.getElementById("uploadInput").files[0].type
Returns the mime type of the first file. I don't believe that the method used to perform this identification is mandated by the standard.
If this is insufficient then you could read the file locally with the FileReader apis and do whatever tests you require. This could be as simple as checking for the magic bytes present at the start of various file formats to fully validating that the file conforms to the relevant specification. MDN has a great article that shows how to use various bits of these apis.
Ultimately none of this would stop a malicious attempt.

Rails Paperclip XML POST File

I am able to 'POST' to a Rails application (with Paperclip) using XML instead of the standard web form (trying to do it from another Ruby script). However, I would like to include a binary file.
Is there any way to include the binary data within an XML tag? Or can I do something like B64 encode the data on the client and then decode it before it hits the Paperclip plugin?
UPDATE:
The browser sends a POST with this data (among others):
Content-Disposition: form-data; name="upload[upload]"; filename="foo.jpg"
Content-Type: image/jpeg
ÿØÿà�JFIF��`�`��ÿþ�Created by AccuSoft Corp.ÿÛ�C�...
I'd like to replicate that, but within XML
The short version is: use type="file", base64-encode the file, and put it inside a CDATA block. I originally found an explanation at this link:
http://techblog.floorplanner.com/2010/02/15/restful-uploading-of-files-using-xml/
That link appears to have died, so I recommend checking out the Internet Archive copy of the blog post:
http://web.archive.org/web/20100825030057/http://techblog.floorplanner.com/2010/02/15/restful-uploading-of-files-using-xml/
Also linked from that post is a gem that implements an encoder for files posted to Rails as XML: https://github.com/nragaz/encoded_attachment

Resources