I'm using a POST request with body to dynamically create a specified file on the server side and streaming it to the client as a response. The problem on the client side is that the file is being downloaded into the response object (browser's cache memory I suppose, as a temporary file) instead of the PC's hard drive.
How can I pass the byte stream directly for the browser to handle and direct into the /Downloads folder or wherever the user has set the downloads go?
The file size is really large and there's not enough space on the gadget's hard drive to create it there and give a link for GET request. So I need to create it on the fly and stream to the client as a POST response.
Right now I've written my code in Angular, but the language doesn't really matter. I'd like to understand how the browser handles the situation.
When I execute the HTTP request, I bet the browser does something with it before it's passed to the socket. And I'm sure the browser does something with the received request too before passing it to the piece of code which performed the request.
I mean can you only by setting the response headers make the browser download the file into /Downloads? What happens then to the waiting HTTP request if the packets are "stolen" by the browser? Or when the response headers arrive to the response object, can you somehow notify the browser that the body of the response is a file byte stream we wish to download into /Downloads?
And I have the possibility to modify my server code too.
EDIT More detailed explanation:
My server is sending the 5GB file to the client. Instead of just receiving that file in the temporary memory of the browser I would like to save the file directly on hard drive.
But naturally the browser prevents the direct access to the users computer so I can't write it there. So how do I pass the byte stream for the browser to handle and save into a file?
Ok, I have solved the problem. So if you send a file request yourself to the server from your javascript code the browser will just pass the received response directly to your response object, but you can't store it on the hard drive without some external (browser supported) tools.
What I mean is that if you perform any kind of $http.post() or .get() from your scripts the response will be passed to the $http.post().then(function(response){...}) directly and it's passed only after the whole response is received. Meaning that if you're expecting a file with the size of 5GB it will fail for being too large to be received inside the response object.
Instead what you have to do is to trigger the download in another way. What I did in my code is that I built a hidden
<form method="POST" action="/set.uri.here/" id="download">...</form>
and when the user clicks the button to download the file, I run a function that builds the body of the form and then submits it. Which looks like
var form = document.getElementById("download");
// magic here... create the body for the form and so on
form.submit();
This way you can pass the request to be done by your browser so that then the response will be also handled by the browser. This is the crucial difference between doing the request yourself or by the browser. If you do the request yourself then the browser won't download the object but you will receive it yourself to do something with it.
If you wish the browser to download the object, then, make the browser do the request for the object as well!
Related
This is part of an experiment I am working on.
Let's say I upload a file eg: .psd (photoshop file) or .sketch (sketch) through the input type file tag, it displays the name of the file and can be downloaded as a .psd / .sketch on click of a button (without data corruption)
How would this be achieved?
Edit 1:
I'm going to add a bit more info as the above was not completely clear.
This is the flow:
User uploads any file
File gets encrypted in the client before sending to a sockets.io server
User on the other end receives this file and is able to decrypt and download.
Note: There is not database connected with the sockets.io. It just listens and responds to whoever connected to the server.
I got the enc/dec part covered. Only thing is uploading and store as ? in a variable so it can be encrypted and doing the opposite on the recepient end (dec and downlodable)
Thanks again in advance :)
I think these are your questions:
How to read a file that was opened/dropped into a <file> element
How to send a file to a server
How to receive a file from a server
When a user opens a file on your file element, you'll be able to use its files property:
for (const file of fileInputEl.files) {
// Do something with file here...
}
Each file implements the Blob interface, which means you can call await file.arrayBuffer() to get an ArrayBuffer, which you can likely use directly in your other library. At a minimum, you can create your byte array from it.
Now, to send data, I strongly recommend that you use HTTP rather than Socket.IO. If you're only sending data one way, there is no need for a Web Socket connection or Socket.IO. If you make a normal HTTP request, you offload all the handling of it to the browser. On the upload end, it can be as simple as:
fetch('https://files.example.com/some-id-here', {
method: 'PUT'
body: file
});
On the receive end, you can simply open a link <a href="https://files.example.com/some-id-here">.
Now, the server part... You say that you want to just pass this file through. You didn't specify at all what you're doing on the server. So, speaking abstractly, when you receive a request for a file, you can just wait and not reply with data until the sending end connects and start uploading. When the sending end sends data, send that data immediately to the receiving end. In fact, you can pipe the request from the sending end to the response on the receiving end.
You'll probably have some initial signalling to choose an ID, so that both ends know where to send/receive from. You can handle this via your usual methods in your chat protocol.
Some other things to consider... WebRTC. There are several off-the-shelf tools for doing this already, where the data can be sent peer-to-peer, saving you some bandwidth. There are some complexities with this, but it might be useful to you.
I have a JavaScript application that uses REST API server as a data provider.
There is one method on API that takes GET request and returns raw response that contains email (as far as I can see there is some kind of .eml content).
I use a simple xmlhttprequest.
The question is: how could I take a response (the file content) and delegate it ti browser so the browser can begin a downloading process ?
Is it possible to do at all with GET method ?
Javascript does not support downloading and saving arbitrary files on a user's computer due to obvious security concerns.
There are, however, a few ways to indirectly trigger the download using javascript. One of those ways would be using an invisible iframe and setting the source to the path towards the file.
You might be waiting for browsers to implement window.saveAs, see also the question Using HTML5/Javascript to generate and save a file
There are several snipets you could try, for instance https://github.com/eligrey/FileSaver.js or https://gist.github.com/MrSwitch/3552985
Depending on how you have your client running you could use local storage.
to store the item
localStorage.setItem('NAME', DATA);
and to retrieve
localStorage.getItem('NAME');
and to delete
localStorage.removeItem('NAME');
and then set up a callback or promise to render into the html. If you use axios you can set this up with a promise https://github.com/mzabriskie/axios
The goal is to generate thumbnails/previews server-side only if it cannot be done client-side.
The Fine-Uploader documentation states:
However, you should take care to not blindly return a thumbnailUrl for
images that are already previewable in modern browsers unless your
server intends to orient them correctly first.
How does the server know if Fine-Uploader is able to generate the preview client-side or not?
There is no way to reliably determine if a specific preview has generated successfully before the file upload request has been sent, as preview generation is an asynchronous process and may complete after the request has been sent. However, you can determine if the current browser has the ability to generate image preview by checking the imagePreviews feature flag. If qq.supportedFeatures.imagePreviews is true, then the current browser is capable of generating client-side image previews. If this flag is false you can set a parameter with all upload requests that instructs your server to return an image preview URL instead. For example, you can setup your params option to do this:
request: {
params: isBrowserPreviewPossible: qq.supportedFeatures.imagePreviews
}
The isBrowserPreviewPossible param w/ value will be sent with every upload request to your server. This is demonstrated in the live S3 uploader at FineUploader.com.
In a Rails2 Webapp, I am creating in javascript a form to forge a request to download a file. In the controller, I render the response using send_file so the file is downloaded.
There is a rather long process going on looking up the file to download and meanwhile I have the client waiting for the file to start being downloaded. For this reason, as soon as the client clicks the download button I display a small massage saying "Requesting file...".
Problem:
How can I (on javascript side) know when the response is rendered (aka the file starts to download) so I can hide the message I am displaying? I use ajax everywhere and I throw the showMessage method in the "before" part of the call and the hideMessage in the "complete" part of the jquery ajax call. But since I cannot request a file to be downloaded with an ajax call I have to do it trough a form but then I don't know how to realize when I get the repsonse back (or the file starts to download)
The basic idea is to send a cookie along with the file. Some javascript code checks the cookie periodically. When javascript gets the cookie, you know the downloading begins.
You can find sample javascript code here (server code in Java) and here (server code in ASP.NET).
In Rails, the cookie could be sent like this:
cookies['download_token'] = params[:download_token]
send_data ...
I have an Flash MP3 Player that I am planning to use on my site, and what I am attempting to do (since the Flash element itself doesn't have a built in callback) is to listen for any HTTP Request it may make. Currently I can see the HTTP request form within my Chrome Timeline, and it tells me exactly the name and location of each files being requested as it is running through the playlist —- it shows up as "Send Request". The purpose for me attempting to do this is to possibly grab the file name, scan it via PHP, and return its ID3 image to the browser via jQuery. Is this possible?
Retrieved from Chrome Timeline:
Send Request - Details
Self Time 0ms
Aggregated Time 0ms0ms0ms
Duration 303ms (at 1.49s)
Resource Track-02.mp3
Request Method GET
Used Heap Size 23.87MB of 41.62MB
Browsers do not provide an API for listening for any HTTP request.
Something you could try is serving the mp3 files via a script. This script could then store the loaded file's details somewhere. Then have your JS code query another script which returns the stored details.