I want to upload a binary file using json.
I choose Json because with the file I would also like to send additional information.
I am going to do this by -
Select a file in the file input tag.
Use the HTML5 File Reader Api to read a file first.
Convert the file content into base64.
Add the base64 content to a JS object in a data uri format.
Convert the JS object to json and post it to the server.
I wonder if this is the only legitimate way to achieve my goal? Also, if there is a plugin already available somewhere which give me this ability?
No, this is not the only way - one of the other ways is just to submit a form with a file in it. Such form uses multipart/form-data content type.
See W3C documentation on the subject:
The content type "application/x-www-form-urlencoded" is inefficient for sending large quantities of binary data or text containing non-ASCII characters.
The content type "multipart/form-data" should be used for submitting forms that contain files, non-ASCII data, and binary data.
So, there is no need to reinvent the wheel - browsers already support sending the files along with additional information, in a simple way. You just create a form where the user can enter data and select files, then all of them are sent to the server with multipart/form-data content type, and your web framework should be able to understand that it deals with both files and textual data.
Related
I have been developing a web app where the user can upload a PDF file, and then later retrieve it and view it. What I have been doing to achieve this is having the PDF uploaded to a PostgreSQL database as bytea datatype (the column is called "attachment"), and then having nodeJS offer up this data to be fetched back and turned back into a PDF to view.
However I have been struggling to convert the data back into a valid PDF. This is the method I am using so far.
var file = new Blob([res[i].attachment], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
document.getElementById("pdf_box").data = fileURL;
The #pdf_box identifier refers to an object element in a HTML file which is used to display the PDF (this has been shown to work when I provide the file location of a dummy PDF file to the data attribute of this element).
The res[i].attachment is also shown to provide valid buffer data in JSON format, with an example provided below:
"attachment":{"type":"Buffer","data":[91,111,98,106,101,99,116,32,70,105,108,101,93]}
When I load the created fileURL into the data attribute of #pdf_box however, I get an error indicating along the lines of an invalid PDF file. My research so far appears to indicate this may be because the data is coming in as buffer whereas it needs to be in byte form, but I haven't found much that helps show me how this may be achieved or if there is a way to convert between the forms with the data I have access to? I have also seen occasional reference to a method called pdf.create(), but I cannot find documentation on this and I assume it must belong to a third-party library for JS.
If you know of any information that can help me with understanding what my problem is and what to search to figure out a solution, it would all be greatly appreciated, thank you.
To all reading this question, this method does not seem possible and would likely be incredibly inefficient to implement. If you send a string to nodeJS larger than the MTU of your link to this server (anywhere between 68 bytes and >1500 bytes depending on every component of your network) the packet will be silently dropped with no attempts to resolve or throw an error. What you must do is take the approach of using "multipart/form-data" encoding to send any files to the server (more on this found here).
It should also be mentioned that uploading a file to the database is not recommended in any capacity (due to databases being quite inefficient storage for large amounts of data) and what should be done is to upload a reference to the file path or URL to find the file at. Then on the client-side this file could be rendered as such when you have retrieved the file location...
<object id="pdf" data="../files/test.pdf"></object>
To change the data attribute, the following can be done...
document.getElementById("pdf").data = "../files/test2.pdf";
Sometimes when making an HTTP request to download a file (e.g. PDF, XLSX, etc.) from the own webserver, it is necessary to use the HTTP method POST, because it requires dynamic input data. I have been trying different ways to reduce that to one single HTTP request for best performance, but could not succeed.
As JavaScript with the XMLHttpRequest object (AJAX) can not "download" files, I guess it requires an HTML workaround. The only working solution I found for that case is generating a form element wrapping input elements containing the data. I could not find a way how to send boolean values via this, as AJAX is able to. That would mean: it is not suitable for a standardizable implementation.
My question is: How can I download a file via one POST request which can include boolean values (JavaScript)?
In case it is important: The backend system I use is Ruby on Rails
As #Pointy mentioned, boolean values are always translated to strings in HTTP communication. I was wrong about that in my question. That means, converting a JavaScript JSON string or a classic object to an HTML form (then submitting and deleting it) works!
Actually sending an AJAX request and then manually triggering a link click to the generated file has the advantage of being able to use a progressbar.
I know that blob is a data type for binary data as integer is a datatype for int. As they say, It's used to store files directly in database (we move our audio file into blob, and save that blob in database).
Question 1) why to store blob for audio if I can just put the audio in storage for example path /var/www/audio.mp3 and in database I store path_name /var/www/audio.mp3?
Question 2) which is better ? how netflix stores movies? just blobs or what?
Question 3) Curious if there're any cons or prons if you could just give me ideas so that I know when to use them .
Putting the blob in the database, rather than a file, allows you to grow to multiple servers with load balancing. If you put the data in files, you would have to replicate the files between the server. Most databases have built-in replication features, this isn't as easy for regular files.
Better to use external storage/cdn for serving such kind of large content.
How Netflix and our works? They upload content on external bucket i. e. S3 and write file name in db for identification. According to user file access frequency that file cache on CDN/edge location. User will get awesome experience while content server from their nearest edge location
With blob you can store all kinds of stuff.
Do you communicate with an API via SOAP or JSON and want to store it in the database? Use a blob. Want to log what a user filled into a form when it threw an exception? Store the entire post as a blob. You can save everything as is. It's handy for logging if you have different data formats. I know an API which expects some data via SOAP and some as JSON. To log the communication I use blob because the response may be in XML, JSON, a number (http code 203 for empty but accepted) or an exception as array.
My application has to generate reports which should be available for download in XLS format. I have built a REST API using Django Rest Framework and there is an endpoint for report generation. It accepts POST requests with JSON body (report parameters, like from, to, etc., but there is also some data that represented with JSON objects) and returns JSON result. I successfully use it from Javascript, render the report as an HTML table and it works just fine.
My problem is that I need to allow users to save the report as an .xls file with a decent filename (like myawesomereport.04.12-10.12.xls. I tried JS data url approach, but as far as I understand, there is no way to set a filename if you go with that option (except setting a download attribute on an a tag, but its support is limited, so it's not the way to go). I thought that maybe I should open a new window with my API endpoint's url appropriately formed, so it outputs an XLS file, but the problem is that I do not understand if there is a way to send JSON with that request.
How should I approach this problem?
You can set the filename in the backend, by using the header Content-Disposition, so that in the frontend you can use a standard <a> tag.
In DRF, it would look like this:
response['Content-Disposition'] = 'attachment; filename={}'.format(
file_name
)
I'm using jsOauth-twitter to upload an image to twitter which calls the update_with_media api method. It looks like it needs the actual image data. This is already on my webpage inside a normal <img src="localfile"> tag.
Using Javascript, can I get at the actual image data (JPEG) to pass it to the function? Is it available in the DOM? I need the raw image data so I can pass it to twitter as application/octet-stream, so base64 is no good to me.
It looks like the API requires the form to be sent as multipart/form-data, which means the media[] parameter is expecting a file rather than binary or base64 encoded data. If you use HTML file input inside a form, this should be fairly straightward.
If you must use the <img> tag, then it would be difficult. All I can think of is draw the image to a <canvas>, obtain a base64-encoded URI with toDataURI(), decode it to obtain the raw image data using window.atob(), then build the multipart/form-data POST body manually. This answer has some sample code for the first couple of things.
The Blob API may help in creating a file-like object which your OAuth library can accept (rather than manually building the request body), but its not very well supported yet.