I have successfully returned a thumbnail() request (using the Dropbox SDK) in my rails app, but I don't understand how to process the response. I would like to show the thumbnail on a webpage.
I also tried to save the response to a tmp file, but get a UndefinedConversionError ("\xFF" from ASCII-8BIT to UTF-8) error.
I'm actually doing exactly what you are asking for. What I did was to convert the returned bytes into a base64 string. In C# it's quite easy as there is a convert function to do that.
On the webpage you then have to set the src attribute of a img tag to
<img src="data: image/jpg;base64,PlaceBase64StringHere"...../>
There is a little overhead in the converted string, but it's very easy to handle and you use the power of the client browser to render the image.
Related
i read this post convert image to base64 with flutter but this is about converting image file to base64. How to convert online url to base64.
Right now i can think of one solution that is to store image in path and get that file path and convert it. thats how this post showing.
is there any other sort way to convert online image uri to base64?
Well to convert the image you need the image data otherwise there's nothing to convert. So the step for the most effecient would be.
Perform get request to the image url
Read all the bytes from the response body
Convert to base64
Save the base 64 string locally or use how you please.
You don't have to save it. Just keep in mind if the user closes the app or it stops at any point during this process you'll have to start it from the beginning because you're not saving the image to disk.
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
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.
I've built a DataSnap REST server using Delphi XE2 and I've added a server method for uploading files via TStream :
function TServerMethods.updateUploadFile(sFilename: string; UploadStream: TStream): string;
I want to be able to call this from a number of different clients (Android, iOS etc) and I've been testing the method using various REST clients such as Postman (Chrome plugin). However so far I cannot get it to accept the content for the HTTP POST body. Whenever I send the POST command I always get the following response :
{"error":"Message content is not a valid JSON value."}
I've tried using various different 'Content-Type' settings but nothing seems to work. It looks as though DataSnap is insisting on the content being JSON? I've tried pasting some valid JSON into the content area but this also gave the same error response.
Has anybody successfully used TStream as an input parameter for a DataSnap server method? Should I be doing it another way? I've used TStream as an output parameter for downloading files many times and it works well, this is my first attempt at uploading.
UPDATE
I made a quick Delphi DataSnap client to test the uploadFile server method and this all works great. I then used Fiddler to examine the POST command the Delphi client uses to send the TStream in the content body, and noticed it is a JSON array of integers (bytes) e.g. [37,80,68,70,45,49,46,51,13,10]. So I can see that I could modify my Android/iOS clients to convert the binary data to this byte array format before POSTing, but this is an overhead I could do without. If DataSnap streams raw binary when TStream is a return parameter, why can't it stream raw binary as an input parameter?
It seems when adding content data to the request body in a POST command, DataSnap server insists that this data is always JSON. This is why when using TStream as an input parameter, the stream data is converted to a JSON array of integers (bytes) by the Delphi DataSnap client. This format is very size inefficient as with upto 3 digits per byte, plus the comma, the size of the data being uploaded can grow by as much as 4 times.
What I have therefore done instead is to encode the data to upload in Base64. My server method now looks like this :
function TServerMethods.updateUploadFile(sFilename: string; Base64Data: TJSONObject): string;
Notice I'm wrapping the Base64 string in a TJSONObject. This is because if you just specify a String type, the Delphi DataSnap client will call the method with a GET and attempt to put the whole Base64 string in the URL path, causing a 'Connection Closed Gracefully' error. Using a TJSONObject forces DataSnap to use a POST and put the data in the content body. The JSON object passed is a single pair object :
{"UploadedData":"JVBERi0xLjMNCiXi48B5SiWGTK3PaY.........."}
This way the size of the data uploaded is much smaller and faster to transfer. I'd still prefer to be able to stream the raw data in the content body but DataSnap doesn't allow this.
I'm using restclient for a multipart form to send data to a restful web service (it's Panda video encoding service).
The trick though, is that the file I am passing into restclient (Technoweenie branch) is coming from my own form that a user submits.
So, lets walk through this. A user posts a file to my rails app. In my controller, it receives the file from params[:file]. I then want to pass params[:file] down to Panda using RestClient.
The error I'm getting is on the Panda server follows. I noticed that the file param in the stack trace is in a string as well (which I assume is Panda turning into a string for a nicer stacktrace).
~ Started request handling: Wed Aug 12 18:05:15 +0000 2009
~ Params: {"format"=>"html", "multipart"=>"true", "account_key"=>"SECURE_KEY", "action"=>"upload", "id"=>"SECURE_ID", "controller"=>"videos", "file"=>"#<File:0xcf02ca4>"}
~ 9bfb1750-6998-012c-4509-12313900b0f6: (500 returned to client) InternalServerErrorcan't convert nil into String
/var/local/www/panda/app/models/video.rb:246:in `extname'
/var/local/www/panda/app/models/video.rb:246:in `initial_processing'
/var/local/www/panda/app/controllers/videos.rb:79:in `upload'
I doubt you can really pass a CGI-style upload param from Rails into restclient and expect it to work.
A regular upload in Rails would have quite some extra attributes which do not belong in a posted resource (like the original filename and so on), and a Rails upload contains an IO with the actual file data. Also a file upload object in Rails might be a Tempfile handle and might be a StringIO - depending on the size of the upload.
What you effectively need to do is "repackage" your upload for rest-client to handle it properly, and pass the repackaged and rewound Tempfile object to restclient. Maybe you can get away with just picking the upload object itself instead of the whole params[:file]
Confirm that your restclient action can save locally first. If the action cannot save locally, then you will have a better idea where to look while trouble shooting.
Looks like the problem is with rest-client's posting of the file, check out an alternative method for posting like curb.
Lots of examples for posting multipart form data on this question: Ruby: How to post a file via HTTP as multipart/form-data?