How to do nice and simple file uploading in javascript? - javascript

All I want is:
select a file
small progress bar (unless it is not simple)
fail/success confirmation on client side
trigger action on server side.
all that without page reloading
Except that, the simpler the better.
Snippet would be most welcome.

There are plenty of scripts and tutorials around. Check for example http://www.ajaxf1.com/tutorial/ajax-file-upload-tutorial.html

Apparently that's not as trivial as one might think, since you can't just take the body of a form, containing an <input type='file'/> tag, and submit that.
But you can submit the form with a target of another <iframe/> and then poll the server with a XMLHttpRequest object for status updates, that however, requires that your sever-side script, that handles the upload, does so in a asynchronous manner, otherwise you will only get a status update once the file has been fully uploaded, not the kind of progress status updates you want. I think this is a challenge for most web frameworks to date, but I have never actually had any reason to dig into it. Sounds fun though...
If you just want to submit the file, independently of the actual form, you'll do the same, but you don't have to worry about the progress status updates.
What you can do, is to replaces the <input type='file'/> once the upload completes, with a <input type='hidden'/> containing the server-side ID of the recently uploaded file. That way you'll know when the user hits save, what files you'll want to actually save.
That hidden thing can also be a checkbox, which would let you undo a file upload, by simply unchecking that checkbox before hitting save.

File uploads using the XMLHttpRequest object is not possible in all browsers (only Firefox and Safari/Chrome support it), so for a cross-browser implementation use the <iframe> trick.
If you want a real XHR file upload, I have written an extended article on how to do it in Firefox 3. It's so low level that you actually have to build the actual HTTP request from JavaScript strings.

Maybe GearsUploader will fit.

Related

How to manipulate form file input before POST

I have a form which includes an input type="file" to upload an image, and I want to be able to manipulate that image before submission.
(I may want to crop or resize it using an existing jQuery library, for example. I'm posting to WordPress and am tied to gravity forms, which means I can't use a plug-in such as jQuery-file-upload which includes server-side handling too, so my question is more generic.)
I'm trying to understand what happens on submit and how the browser constructs the post to be handled by the server.
If a user has selected a file, can I take that file and do something with it in javascript, and then on the form submit have the browser take my amended version from memory rather than the original version linked to in the input field?
[EDIT]
So, I've discovered some useful insights. Anyone looking at this, here is a useful thread here on SO.
When a user selects an image on a file input field, I can use html5 canvas to manipulate it. I need to then convert it back to a binary file to upload (via canvas.toBlob() in the most modern browsers, or using the technique mentioned in the above link for older browsers).
Then what do I do with it? I can POST it via Ajax as per this Mozilla developers article and for most people this will be fine.
My problem is that I am tied to using Gravity Forms and I need to let it handle the form submission.
Which means I need to manipulate my existing form and let the user hit the submit button as normal.
Where my form has
<input type="file" name="input_3" id="input_3_3">
I have tried in JavaScript:
document.getElementbyId('input_3_3').value = myBlob;
but it appears that I can't assign the blob to the input field.
Reading around, the solutions which involve Ajax make use of FormData objects, and I thought I might be able to append the field but that doesn't seem to work (the form on the page in the DOM and the FormData object are not the same thing?).
So, that's where I'm stuck.
In theory you can use blob , but practically it is not good solution because it is not supported in all browsers , and there is no current javascripts library to process images , so the best bet is to send it so server and let the server process it .

How do modern web-apps/sites do postbacks? javascript/ajax, <form> or X?

I am curious to know how "modern" web-apps/sites do postbacks, meaning when they are sending back user-input to the site be processed.
Do modern sites still use the old fashion <form>-tags or do they use some sort of javascript/ajax implementation? or is there even a third option?
I tend to use both, where a full page refresh from a normal <form> submit works, but if JavaScript is enabled you hook up to the submit event and override it. This gives you fancy AJAX if possible, and graceful degradation if it's not.
Here's a quick example (jQuery for brevity):
<form type="POST" action="myPage.htm">
<input type="text" name="UserName" />
<button type="submit">Submit me!</button>
</form>
If the user has no JavaScript, no problem the form works. If they do (and most will) I can do this:
$(function() {
$("form").submit(function() {
$.ajax({
url: this.action,
type: this.type,
data: $(this).serialize(),
success: function(data) {
//do something with the result
}
});
});
});
This allows the graceful degradation, which can be very important (depends on your attitude/customer base I suppose). I try and not screw over users without JavaScript, or if a JavaScript error happens on my part, and you can see from above this can be done easily/generically enough to not be painful either.
If you're curious about content, on the server you can check for the X-Requested-With header from most libraries and if it's present, return just the <form> or some success message (since it was an AJAX request), if it's not present then assume a full page load, and send the whole thing.
It will vary depending on what exactly is being done, but most web-apps will do a combination of AJAX for short content (esp where live/interactive updates are helpful without requiring a page refresh) and "old-fashioned" forms for longer content wherein a full page load is not an issue.
Note that nothing about AJAX prevents its use for long content as well as short.
Also note that from the stand-point of the code driving the server app, there is not necessarily much difference at all between a request coming from a standard form or a request coming from an AJAX submission. You could easily structure a single script to properly respond to both types of request (though in some cases you can save bandwidth by sending a shorter "data-only" response to the AJAX version, since the client-side code can be responsible for parsing the data into meaningful content).
Basically, there are three models.
The traditional form model uses form postbacks for every action that requires going to the server, and may use javascript to perform client-side tasks that make the user's life easier without compromising security (e.g. pre-postback validation). The advantage of this is that such a web application, if written correctly, will work without needing any javascript at all, and it is easier to make it work on a wide range of devices (e.g. audio browsers).
The server-centric ajax model uses ajax calls to provide partial page refreshes; the page is built like in the traditional model, but instead of triggering a full page post-back, client-side script uses ajax calls to send clicks and other events, and retrieves information to replace a part of the document (usually in JSON or XHTML form). Because you don't post the entire page every time, the response is usually quicker. This model is useful if you want to use ajax where possible, but still want to be able to fall back to traditional postbacks if javascript isn't available.
Client-centric ajax takes a different path; the core idea is that you write your entire application in javascript, using ajax to exchange data, not markup. When you click a button, the application sends a request to the server, and receives data. The data is then used for further processing on the client. This is more flexible and usually faster than the other methods, but it requires good knowledge of javascript. Applications written in this style generally don't work at all when javascript is disabled on the client.
Most decent web applications try to put progressive enhancement. Meaning that a simple old fashioned button click results in a form post which can be handled by the server. This is for the scenario of people who use an old browser or turned off javascript for some reason.
The enhancement can be done by using hijaxing. Meaning that that same page can perform, with the help of some ajax, the form post to the server but not the entire page. This enables users with javascript enabled to have a better user experience.
old fashion -tags or do they use some sort of javascript/ajax implementation?
In order to have javascript to work on something you still need that somethingl old fashioned tags. Web applications can be structured down to 3 major parts:
Content: HTML
Layout: CSS
Behavior: javascript/ajax

Ajax /jQuery finding if user completed the download

Here is what I am trying to do: I am making a custom text file containing a test. This test is unique to the user and well I don't want my server to stack all those text files.
Is there a way to use Ajax/JavaScript/jQuery to find if the user has already finished the download and if they have get a return value (1 if finished) so the response can be sent back to the PHP file and it can delete that file off the server (real-time like)?
I know there are plenty of ways to do this using PHP. Sort of like run clean up upon user log out and so on but I wanted to try using the method above since it can have many other applications that might be cool to use. I tried most search engines but they have nothing close to what I need.
Why do you need to store them in a file? Just use a PHP script or such that creates the test and outputs it directly to the user. That's how it will get deleted when the download is complete.
If it's important you may want the user to return to your server with the hash of the downloaded file. If the hash matches you know two things:
1. The user downloaded the file successfully
2. It's now ok to delete the file
Well it is very simple. I don't know how to make a PHP webpage send itself to the user other than to make the PHP make a text file and force send that to the user. This creates the problem of having so many text files in a temporary folder.
Now if the test required say 15 chapters each having a text or HTML format file then the script neatly zips all those files and sends them to the user. Again falling on the same problem if the user is finished downloading I am trying to get any type of script to delete the temporary zip or text file out of the temporary directory in somewhat real time.
If I could MD5 a downloaded file using JavaScript I welcome it and it would be a hack solution to the problem but how will the JavaScript gain access to the root access of the download folder of the user? There are security issues there if I am not mistaken. Hope this helps round the question a bit more.
I have a good solution for you here using the jQuery File Download plugin I created. It allows for you to get the behavior of performing an Ajax file download (not actually possible possible) complete with Success and Failure callbacks. In a nutshell you can just use the Success callback (that indicates the file download was successful) to perform an Ajax post back to the server to delete the file. Take a look at the blog post for an example on how to use the Success callback option or a demo which uses those callbacks in the context of showing modals to inform the user of what is going on.

What are techniques to get around the IE file download security rules?

Internet Explorer (with default settings, which I generally assume will be in effect on the desktops of the Great Unwashed) seems to dislike the idea of accepting attachment content in an HTTP response if the corresponding request wasn't made directly from a user action (like a "click" handler, or a native form submit). There are probably more details and nuances, but that's the basic behavior that's frustrating me.
It seems to me that this situation is common: the user interface in front of some downloadable content — say, a prepared PDF report — allows for some options and inputs to be used in the creation of the content. Now, as with all forms that allow the user to stipulate how an application does something, it's possible that the input will be erroneous. Not always, but sometimes.
Thus there's a dilemma. If the client tries to do something fancy, like run an AJAX transaction to let the server vet the form contents, and then resubmit to get the download, IE won't like that. It won't like it because the actual HTTP transaction that carries the attachment back will happen not in the original user-action event handler, but in the AJAX completion callback. Worse, since the IE security bar seems to think that the solution to all one's problems is to simply reload the outer page from its original URL, its invitation to the user to go ahead and download the suspicious content won't even work.
The other option is to just have the form fire away. The server checks the parameters, and if there's anything wrong it responds with the form-container page, peppered appropriately with error messages. If the form contents are OK, it generates the content and ships it back in the HTTP response as an attached file. In this case (I think), IE is happy because the content was apparently directly requested by the user (which is, by the way, a ridiculously flimsy way to tell good content from bad content). This is great, but the problem now is that the client environment (that is, the code on my page) can't tell that the download worked, so the form is still just sitting there. If my form is in some sort of dialog, then I really need to close that up when the operation is complete — really, that's one of the motivations for doing it the AJAX way.
It seems to me that the only thing to do is equip the form dialogs with messaging that says something like, "Close this when your download begins." That really seems lame to me because it's an example of a "please push this button for me" interface: ideally, my own code should be able to push the buutton when it's appropriate. A key thing that I don't know is whether there's any way for client code to detect that form submission has resulted in an attachment download. I've never heard of a way to detect that, but that'd break the impasse for me.
I take it you're submitting the form with a different target window; hence the form staying in place.
There are several options.
Keep the submit button disabled and do ongoing validation in the background, polling the form for changes to fields and then firing off the validation request for a field as it changes. When the form is in a valid state, enable the button; when it isn't, disable the button. This isn't perfect, as there will tend to be a delay, but it may be good enough for whatever you're doing.
Do basic validation that doesn't require round-trips to the server in a handler for the form's submit event, then submit the form and remove it (or possibly just hide it). If the further validation on the server detects a problem, it can return a page that uses JavaScript to tell the original window to re-display the form.
Use a session cookie and a unique form ID (the current time from new Date().getTime() would do); when the form is submitted, disable its submit button but keep it visible until the response comes back. Make the response set a session cookie with that ID indicating success/failure. Have the window containing the form poll for the cookie every second or so and act on the result when it sees it. (I've never done this last one; not immediately seeing why it wouldn't work.)
I expect there are about a dozen other ways to skin this cat, but those are three that came to mind.
(Edit) If you're not submitting to a different target, you might want to go ahead and do that -- to a hidden iframe on the same page. That (possibly combined with the above or other answers) might help you get the user experience you're looking for.
There's a whole number of really good reasons IE does this, and I'm sure it's not something anyone would argue with - so the main objective is to get around it somehow to make things better for your users.
Sometimes its worth re-thinking how things are done. Perhaps disable the button, use javascript to check when all the fields are filled out, and fire off an ajax request once they are. If the ajax was successful, enable the button. This is but one suggestion, I'm sure there will be more...
Edit: more...
Do simple submission (non-AJAX), and if the checks fail, send a page back rather than an attachment. The page sent back could contain all the information originally submitted (plus whatever error message to the user) so the user doesn't need to fill out the entire form again. And I'm also sure there will be more ideas...
Edit: more...
I'm sure you've seen this type of thing before - and yes, it is an extra click (not ideal, but not hard).... an "if your download fails, click here" -> in this case, do it as you want to do it, but add a new link/button to the page when the AJAX returns, so if the download failed, they can submit the already validated form from a "direct user action". And I'm sure I'll think of more (or someone else will).....
I have been fighting a similar issue for a while. In my case, posting to a hidden iframe didn't work if my web app was embedded in an iframe on another site (third party cookie issues) unless our site was added to the Trusted Sites list.
I have found that I could break up the download into POST and GET sequence. The post returns a short lived GUID that can be used in a GET request to initiate the download. The POST can do the form validation as well as return the GUID in a successful response. Once the client has the GUID, you can set the src property of a hidden iframe element to the download URL. The browser sees the 'Content-Disposition': 'attachement' header and gives the user a download ribbon to download the file.
So far it appears to work in all the latest browsers. Unfortunately it requires you to modify you server side API for downloading the file.

Is there a way to detect the start of a download in JavaScript?

In our current project we are providing a PDF download that can be customized by the user through an HTML form he submits. It takes several seconds to dynamically generate the PDF and I'd like to visualize this, e.g. by disabling the submit button until the download starts. Unfortunately, I couldn't find a way to detect when the download starts*. So I wouldn't know when to re-enable the submit button.
I already tried to specify an IFrame as the target of my HTML form, hoping that the onload event would be triggered. It is not, however -- probably because the PDF is sent with a "Content-disposition: attachment" header and it is not actually loaded into the IFrame.
The only solution I can think of right now involves generating the PDF to a temporary file on the server, which I would like to avoid.
*)Let me clarify this: I wouldn't need to know if the download was finished or even if it was really started. I'd like to detect the point at which the browser will ask the user whether to open or to save the file. I guess this happens when the browser receives the HTTP header.
If I was you I would do an AJAX call to the server with the information, generate the file, then return the file name/id/whatever back to the javascript, which then makes window.location something like download.php?id=x (but the file was already generated, so it is just setting the headers and reading it out) at which point you can re-enable the submit.
What you want is to be able to detect when the size of the downloaded file changes from 0 to a positive value. As far as I know it is impossible to do that with javascript - you need a plug-in that can access the client's file system.
A recommended work around: Create a session per download. Have the client poll the server about the status of the download. This could be "non existed", "not started", "started", "finished". You need some server's side work to persist and update the status of the download plus an AJAX framework.
The simplest solution would be to estimate the time (generously) and do it that way. It's a hack, but it gives the desired effect. The other option might be to submit the form with a callback using Ajax to submit the form and have the generator return details to the calling page. http://www.jquery.com/ might be a good place to start for that option.

Categories

Resources