jQuery Upload Progress and AJAX file upload
Asked Answered
U

2

72

It seems like I have not clearly communicated my problem. I need to send a file (using AJAX) and I need to get the upload progress of the file using the Nginx HttpUploadProgressModule. I need a good solution to this problem. I have tried with the jquery.uploadprogress plugin, but I am finding myself having to rewrite much of it to get it to work in all browsers and to send the file using AJAX.

All I need is the code to do this and it needs to work in all major browsers (Chrome, Safari, FireFox, and IE). It would be even better If I could get a solution that will handle multiple file uploads.

I am using the jquery.uploadprogress plugin to get the upload progress of a file from the NginxHttpUploadProgressModule. This is inside an iframe for a facebook application. It works in firefox, but it fails in chrome/safari.

When I open the console I get this.

Uncaught ReferenceError: progressFrame is not defined
jquery.uploadprogress.js:80

Any idea how I would fix that?

I would like to also send the file using AJAX when it is completed. How would I implement that?

EDIT:
I need this soon and it is important so I am going to put a 100 point bounty on this question. The first person to answer it will receive the 100 points.

EDIT 2:
Jake33 helped me solve the first problem. First person to leave a response with how to send the file with ajax too will receive the 100 points.

Undershirt answered 31/1, 2011 at 22:36 Comment(6)
I see that it uses browser sniffing to detect Safari (browser sniffing is usually frowned upon), so progressFrame is only used with Safari/Chrome (I don't know why). The part where the error is occurring seems to be where the script tries to reference progressFrame just by looking for its name in the global scope instead of using a function like document.getElementsByName.Stanhope
I'm not sure what you mean by "send it using AJAX when it is completed" -- Isn't the progress bar representing the progress of the submission? Doesn't that mean that it is already sent once it is complete? Do you mean that you want the original form submission to be driven by AJAX so it doesn't cause a page refresh after?Asomatous
Yes. Yes, but it acts like a form submission. Thats exactly what I want.Undershirt
If the question how do you send data with an HTTP POST over XMLHttpRequest using jQuery, then there is jQuery.postDevisor
Do the answers below work for you? If not, can you comment on the answers. I'm slightly confused as a result of all of the edits and want to try to solve your problem. Thanks. BTW I included a link for JQuery's Multiple File upload plugin.Simonette
customphpfunctions.blogspot.in/2014/12/…Duel
C
219

Uploading files is actually possible with AJAX these days. Yes, AJAX, not some crappy AJAX wannabes like swf or java.

This example might help you out: https://webblocks.nl/tests/ajax/file-drag-drop.html

(It also includes the drag/drop interface but that's easily ignored.)

Basically what it comes down to is this:

<input id="files" type="file" />

<script>
document.getElementById('files').addEventListener('change', function(e) {
    var file = this.files[0];
    var xhr = new XMLHttpRequest();
    (xhr.upload || xhr).addEventListener('progress', function(e) {
        var done = e.position || e.loaded
        var total = e.totalSize || e.total;
        console.log('xhr progress: ' + Math.round(done/total*100) + '%');
    });
    xhr.addEventListener('load', function(e) {
        console.log('xhr upload complete', e, this.responseText);
    });
    xhr.open('post', '/URL-HERE', true);
    xhr.send(file);
});
</script>

(demo: http://jsfiddle.net/rudiedirkx/jzxmro8r/)

So basically what it comes down to is this =)

xhr.send(file);

Where file is typeof Blob: http://www.w3.org/TR/FileAPI/

Another (better IMO) way is to use FormData. This allows you to 1) name a file, like in a form and 2) send other stuff (files too), like in a form.

var fd = new FormData;
fd.append('photo1', file);
fd.append('photo2', file2);
fd.append('other_data', 'foo bar');
xhr.send(fd);

FormData makes the server code cleaner and more backward compatible (since the request now has the exact same format as normal forms).

All of it is not experimental, but very modern. Chrome 8+ and Firefox 4+ know what to do, but I don't know about any others.

This is how I handled the request (1 image per request) in PHP:

if ( isset($_FILES['file']) ) {
    $filename = basename($_FILES['file']['name']);
    $error = true;

    // Only upload if on my home win dev machine
    if ( isset($_SERVER['WINDIR']) ) {
        $path = 'uploads/'.$filename;
        $error = !move_uploaded_file($_FILES['file']['tmp_name'], $path);
    }

    $rsp = array(
        'error' => $error, // Used in JS
        'filename' => $filename,
        'filepath' => '/tests/uploads/' . $filename, // Web accessible
    );
    echo json_encode($rsp);
    exit;
}
Cleland answered 31/1, 2011 at 22:36 Comment(20)
This is a feature available only in XMLHttpRequest2, for a full compatibility list - have a look at caniuse.com/xhr2Hagiographer
@Cleland Do you have the hotblocks.nl tutorial link? not just the demo Thanks in advExegetic
There's no tutorial. Never wrote it. Didn't even make the demo to be this public.Cleland
@Rudie: IE10 seems to support this: caniuse.com/xhr2. IE10 is not that bad. Browser war has some advantages. FF9 seems to be the problematic one when it comes to file uploads: you cannot clear file input!Rotenone
Yeah IE10 is much better AND with default automatic updating (but still configurable unfortunately). Let's hope they can keep up with the big boys. (This demo has been working in Chrome for 2+ years btw.) (I actually noted this too some ago.)Cleland
@Cleland Could you please post a simple code for server side handling of the data recieved?Lorilee
@NeilMartin I've added PHP example code to the end of the answer. Obviously you'll want to do something else with it.Cleland
This took a while to understand but it's sound. One note, if you don't want to upload immediately on form change but have an UPLOAD button you can do something like this (what I ended up doing...) document.getElementById('files').addEventListener('change', function(e) { file = this.files[0]; }, false); $('#mybutton').click(function() { /* ...proceed much as above using the file object from the change listener ... ...}Koressa
I had to use xhr.upload.addEventListener('progress',...) (with .upload) to have the progress indication working.Fults
@Fults That's why there's a xhr.upload.onprogress in there. Weird that onprogress on xhr does something, but not actual progress. (Or at least that's my finding.)Cleland
Thanks Rudie, sorry your code is fine actually, I had missed the if ( xhr.upload ) {... section. Indeed for me too onprogress on xhr without .upload is fired, but only when the upload finishes.Fults
Ajax is the crappy wanna be who kicked every ones ass, fantastic post fellowObryant
customphpfunctions.blogspot.in/2014/12/…Duel
I'm not sure I understand how to make this work? I would be great if you could make a complete working example and demo online somewhere. Or maybe some guidance on how to make it work and what things are doing?Winged
@Winged I've simplified the example and added a link to a very simple fiddle. What don't you understand? What doesn't work?Cleland
thanks @Cleland for replying, I checked out the fiddle but when I go to select a file nothing happens? That is the part I don't understand? What is missing from this example to make it functional? Forgive me if it's obvious but I'm having trouble connecting the dots.Winged
@Winged Check the console/JS log/devtools. When nothing happens, it's uploading and logging the progress. You can see what it does in the code. If you can't read that, this is probably too advanced.Cleland
@Cleland thanks for that tip, now I can see something is happening. Is there a way for me to send you a private message? I have a form that works using ajax and I'm trying to add a file upload to it. I don't want to get to off topic on this post and add unnecessary comments. I certainly appreciate your help, Im putting in many hours on this and feel I am very close, just need an eye from an expert :) thanks man!Winged
I can see xhr progress: xx% and xhr upload complete in Chrome (version 53) console, but at the server side $_FILES,$_POST and $_GET all is empty arrays. Dо i need to enable something in php to get this work? I'm using php 5.6 builtin server and first example with xhr.send(file);Medulla
what is file size limitLambent
S
19

Here are some options for using AJAX to upload files:

UPDATE: Here is a JQuery plug-in for Multiple File Uploading.

Simonette answered 6/2, 2011 at 10:37 Comment(7)
i used plUpload in several projects with success (multi file upload with progress, supports Flash/Html5/Silverlight etc)Bobbie
AjaxFileUpload is a piece of crap. It's not compatible with any version of jquery newer than 1.5. Also the code is wicked ugly.Demure
@Demure - Good to know. I guess a lot changes in a year. Our hair gets a little greyer and JavaScript libraries stop working with newer software versions...Simonette
To expand @Adam, AjaxFileUpload breaks on ie9+Fourwheeler
All that complaining aside, it's still my favorite. One of these days I'll get around to rewriting the damn thing and putting it on github.Demure
@jmort253 "Multiple File Uploading" link is not working. Please update or remove.Woodcutter
@RanaMuhammadUsman - Take another look now. I believe I found the location of the moved plugins. Hope this helps.Simonette

© 2022 - 2024 — McMap. All rights reserved.