jQuery上传进度和AJAX文件上传

72

似乎我没有清楚地传达我的问题,我需要发送文件(使用AJAX),并且我需要使用Nginx HttpUploadProgressModule获取文件上传进度。我需要一个解决此问题的好方法。我已经尝试了jquery.uploadprogress插件,但是我发现自己不得不重写大部分内容,以便在所有浏览器中使其工作并使用AJAX发送文件。

我只需要能够实现这个功能的代码,并且它需要在所有主要浏览器(Chrome、Safari、FireFox和IE)中正常工作。如果我能获得能处理多个文件上传的解决方案,则更好。

我正在使用jquery.uploadprogress插件从NginxHttpUploadProgressModule获取文件上传进度。这在Facebook应用程序的iframe内部。它在Firefox中可以工作,但在Chrome / Safari中失败。

当我打开控制台时,我看到的是:

Uncaught ReferenceError: progressFrame is not defined
jquery.uploadprogress.js:80
有什么办法可以解决这个问题吗?
我希望在完成后也使用AJAX发送文件。我该如何实现?
编辑:我需要尽快解决这个问题,因为很重要,所以我将在这个问题上支付100分的赏金。第一个回答的人将获得100分。
编辑2:Jake33帮助我解决了第一个问题。第一个回复如何使用ajax发送文件的人也将获得100分奖励。

2
我看到它使用浏览器嗅探来检测Safari(通常不建议使用浏览器嗅探),因此progressFrame仅与Safari / Chrome一起使用(我不知道为什么)。发生错误的部分似乎是脚本尝试通过在全局范围内查找其名称而不是使用像document.getElementsByName这样的函数来引用progressFrame的位置。 - jhartz
1
我不确定你所说的“完成后使用AJAX发送它”的意思 - 进度条不是代表提交的进度吗?这不意味着一旦完成就已经发送了吗? 你的意思是要通过AJAX驱动原始表单提交,以便在提交后不会导致页面刷新吗? - slifty
是的,但它的行为类似于表单提交。那正是我想要的。 - Conceited Code
如果问题是如何使用jQuery通过XMLHttpRequest发送HTTP POST数据,那么可以使用jQuery.post - karlcow
1
以下的答案对您有用吗?如果不行,您可以评论这些答案。由于所有的编辑,我有点困惑,但我想尝试解决您的问题。谢谢。顺便说一下,我附上了JQuery的多文件上传插件链接。 - jamesmortensen
http://customphpfunctions.blogspot.in/2014/12/multi-file-select-preview-without.html - Ima
2个回答

219

现在使用AJAX上传文件是可行的。没错,就是AJAX,而不是类似swf或java这样的不靠谱的模拟AJAX。

以下示例可能对你有帮助:https://webblocks.nl/tests/ajax/file-drag-drop.html

(它还包括拖放界面,但可以轻易地忽略它。)

基本上,它归结为以下内容:

<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>

(演示:http://jsfiddle.net/rudiedirkx/jzxmro8r/)

基本上,它归结为这个 =)

xhr.send(file);

file的类型为Blob时,可以参考http://www.w3.org/TR/FileAPI/

另一种(我认为更好的)方法是使用FormData。这允许您命名一个文件,就像在表单中一样,并且可以像在表单中发送其他东西(包括文件)。

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

FormData 使服务器端的代码更加清晰和向后兼容(因为请求现在与普通表单具有完全相同的格式)。

所有这些都不是实验性的,而是非常现代化。Chrome 8+ 和 Firefox 4+ 知道该如何处理,但我不知道其他浏览器。

以下是我在 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;
}

27
这是仅在XMLHttpRequest2中可用的一项功能,要查看完整的兼容性列表,请访问http://caniuse.com/xhr2。 - YS.
1
@NeilMartin 我已经在答案的末尾添加了PHP示例代码。显然,您会想用它做其他事情。 - Rudie
我不得不使用xhr.upload.addEventListener('progress',...)(带有.upload)来使进度指示工作。 - Florent2
Ajax是个垃圾想要成为的人,踢了每个人的屁股,伙计写得好。 - Tegra Detra
1
我不确定我理解如何使其工作?如果您能够提供一个完整的工作示例和在线演示,那将是非常好的。或者也许可以给一些关于如何使其工作以及这些事情在做什么方面的指导? - drooh
显示剩余15条评论

19

2
我在几个项目中成功使用了plUpload(支持多文件上传进度显示,支持Flash/Html5/Silverlight等)。 - Guillaume86
1
AjaxFileUpload是一坨垃圾。它与任何比1.5更新的jquery版本都不兼容。而且代码非常丑陋。 - Adam
1
@Adam - 很好知道。我猜一年里会有很多变化。我们的头发会变得有点灰,JavaScript库也会停止与新版本软件的兼容... - jamesmortensen
1
扩展@Adam,AjaxFileUpload在ie9+上出现问题。 - 0plus1
1
@RanaMuhammadUsman - 现在再看一下。我相信我找到了移动插件的位置。希望这可以帮助到你。 - jamesmortensen
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接