常见问题解答


客户端


最大文件大小限制是多少?

使用 jQuery File Upload 插件最多可以上传 4 GB 大小的文件。

若使用文件分块上传(分块小于 4GB)方式,则文件大小无上限。

4 GB 的限制是由于某些浏览器限制,这些限制可能会在这些浏览器的未来版本更新中得到解决:

Firefox bug 参考:

https://bugzilla.mozilla.org/show_bug.cgi?id=215450

https://bugzilla.mozilla.org/show_bug.cgi?id=660159

Chrome bug 参考:

http://code.google.com/p/chromium/issues/detail?id=139815

插件是否必须定义表单或 file input 字段?

如果你定义了 url 配置项(也可以是 paramName 配置项),你可以在任何元素上调用插件,即不需要表单或文件输入字段,并且拖放功能仍然有效。

若为了支持无 XHR 文件上传功能的浏览器的话,那么要么必须存在 file input 字段,要么定义 fileInput 配置项。

如何让文件选择框只显示特定的文件类型?

你可以使用 file input 字段的 accept 属性来限制文件类型选择,不过似乎只有 Google Chrome 和 Opera 支持该属性。

限制仅 PNG 图像支持选择的示例:

<input type="file" name="files[]" accept="image/png" multiple>
请注意,这不会限制通过拖放添加的文件,并且并非所有浏览器都支持。
添加大量图片文件时,如何防止页面无响应?

降低 loadImageMaxFileSize 设置或从上传模板中删除“preview”类以避免渲染大的预览图,这可能会阻塞主 JS 线程。

是否可以以编程方式触发文件选择框?

浏览器是不支持以编程方式去触发文件输入框的点击事件的 - 请参阅样式指南

然而,可以使用另一个文件输入按钮来触发文件选择并作为参数传递给 addsend 接口

$('#some-file-input-field').bind('change', function (e) {
    $('#fileupload').fileupload('add', {
        files: e.target.files || [{name: this.value}],
        fileInput: $(this)
    });
});
如何在插件初始化配置项中正确使用 this 关键字?

只需使用 jQuery 的 each 方法this 关键字设置为元素节点:

$('#fileupload').each(function () {
    $(this).fileupload({
        fileInput: $(this).find('input:file')
    });
});
如何限制用户每次只能选择一个文件?

只需从 file input 元素中删除 multiple 属性: Just remove the multiple attribute from the file input:

<input type="file" name="files[]">

请注意,用户仍然可以拖放多个文件。要强制执行一个文件上传限制,可以使用 maxNumberOfFiles 配置项(参阅配置项手册)。

是否可以在上传之前调整图像大小?

这是内置的,目前受最新版本的 Mozilla Firefox 和 Google Chrome 支持。请查看 process 配置项

是否可以拖放文件文件夹?

是的,最新版本的 Google Chrome 支持。

可以通过在 file input 元素添加浏览器私有属性“directory”来允许选择文件夹(而不是文件),不过目前看来似乎只有 Google Chrome 支持该功能:

<input type="file" name="files[]" multiple directory webkitdirectory mozdirectory>
为什么 HTML 源码在引用脚本时缺少协议字符“http:”?

针对当前的 URL 协议而言,这种协议称为相对 URL 协议,也是一种用来引用资源文件的有效方法。

这确保了引用的脚本通过与当前页面相同的协议加载,从而避免了在要求 HTTPS 加载的页面上通过未加密的 HTTP 加载资源时的安全警告。

不过,这要求当前协议要么是“http:”或“https:”才有效,而不是一个文件 URL(“file:”)。

为什么我在自己的循环结构中不能正确输出模板的文件 id?

每一次调用 add 回调时模板都会被渲染。

所以,只要 singleFileUploads 配置项设为 true(默认),那么多文件选择/删除都会被细分为单个 add 调用,因此文件 id 会始终保持为 0

为什么 Firefox 的上传进度显示不了 100%?

请参阅 Firefox Bug #642463

这个 bug 在合并了 f60bbfb2546bc08fe9538d3af56be8d07e634675 代码之后已得到解决。

为什么插件将 1000 字节显示为 1KB(以及 1000000 字节显示为 1MB)?

本插件使用符合国际单位制公制。这与硬盘制造商(例如 Mac OSX 操作系统计算硬盘容量)使用的是同一个单位计量系统。有意思的是,“千字节”、“兆字节”等术语在历史上一直以模糊的含义在使用。相关背景信息,请查看百科上的文章(二进制)。

为什么 file input 字段不显示所选文件的路径?

本插件有内置的 CSS 类并自定义了一套 file input 按钮,其并不现实所选文件的文件名。不过它们是允许删除的,这样便能现实浏览器原生的 file input 按钮 - 参阅样式指南

默认情况下,本插件会在每次选取文件后都替换一次 file input 按钮。该行为可以通过将 replaceFileInput 配置项设为 false 来禁用。

为什么每次选择后都会克隆并替换文件输入字段?

克隆有两个原因:

  • 首先确保即使随后选择了相同的文件(或文件名)也会触发 change 事件。
  • 其次,允许 iframe 传输的上传队列。

如果你有一个文件输入框并选择了一个文件,比如“example.jpg”,然后你出于某种原因中止上传,这时候你选择相同的文件重试上传,是不会触发更改事件的。通过 clone 方法来替换原始的文件输入框(并重置克隆的 value 属性)可以解决以上问题。

iframe 传输依赖文件输入字段,因为 iframe 传输上传是简单的 HTML 表单上传,其中 iframe 作为 POST 目标。如果通过文件输入框选择文件,那么文件被引用时将绑定到该输入框。虽然现在主流浏览器还允许通过 File API 访问选定的文件,但对于 iframe 传输,文件输入框是唯一可用的方式。在提交相关表单之前,你不能使用此文件输入框选择另一个文件,否则将失去原来的已选文件。若要允许使用 iframe 传输进行上传队列功能,你必须保留原始输入框并添加新输入框以供下一次选择。因此,只要使用克隆元素替换原文件输入框(并保留原文件输入框直至表单被提交)也解决了 iframe 上传的队列问题。

fileInput 配置项应该指向插件 change 事件所监听的文件输入集合。所以当原始文件输入框被克隆元素替换时,fileInput 的配置值也要一同更新。

为什么文件名中的斜杆会显示为冒号?(OSX)

当你在 OSX 上创建文件名带斜杠的文件时,它在终端上实际显示的会是冒号。

你可以通过在 Finder 中将一个文件重命名为来进行测试,例如改为“test/example”,然后在终端列出文件夹的内容,这时你将看到显示成了“test:example”。

当你从站点选择或拖放一个文件时,它获得的文件名和通过终端显示的是一样的。造成这种结果是因为斜杆在 OSX 系统中实际上就是目录分隔符:

http://stackoverflow.com/a/13298479

由于 File 对象的 name 属性是只读属性,所以插件在这里不做任何修改:

https://developer.mozilla.org/zh-CN/docs/Web/API/File

插件对于文件名唯一能做的从不支持 File API 的旧版浏览器(旧 IE 版本)的文件中删除路径信息。

为什么当 forceIframeTransport 配置项设置为 true 时,文件多次选择也只显示一个开始/取消按钮?

即便你强制使用 iframe 传输,仍然可以在主流浏览器上进行多文件选择。

然而,Iframe 传输的机制要求,所有选择的文件只能在一次请求中提交上传。因为其是将标准 HTML 表单的文件输入提交给一个隐藏的 iframe,这样的方式就没可能将选择的文件拆分成多批次了。

上述反映到 UI 上就是每个选择框仅显示一组开始/取消按钮来上传。这种情况它也许不是你想要的用户界面,但对于重复利用同一选择框上传,这是最优雅的代码方式。

为什么某些浏览器(即 IE 10 以下版本)不发送自定义 headers?

只有支持 XHR 文件上传的浏览器才支持设置自定义 headers。

有关详细信息,请参阅浏览器支持

本插件仅提供 dragover 事件去实现拖放 copy 效果,并且在事件对象上调用 preventDefault 方法,基于以上两点便可使用跨浏览器文件拖放功能。

插件 dragover 回调的触发器允许防止在函数中返回 false 的行为,这在某些情况下可能很有用。

你可以轻松使用 jQuery 绑定独立于插件的任何拖放事件,例如:

$('#dropzone').bind('dragleave', function (e) {
    // dragleave event handler code
});

服务端


为什么上传完成后 Internet Explorer 会提示下载文件?

本插件为 Microsoft Internet ExplorerOpera 等尚不支持 XHR 文件上传的浏览器使用了 iframe 传输模块。

基于 iframe 的上传要求响应的 Content-typetext/plaintext/html,如果设为 application/json 则会弹出一个不可下载的对话框。

请查看安装指南的 Content-Type 协议部分。

为什么 Internet Explorer 不在 JSON 响应中显示 HTML 代码段?

这取决于 IE 使用 iframe 传输时响应内容是如何解析的。

为什么我提示 JSON 解析错误?

你的 JSON 响应很可能不是一个有效的 JSON 字符串。

可以在 jsonlint.com 上测试你的 JSON 响应是否有效。

要拿到 JSON 响应,可以使用浏览器开发者工具(例如 Google Chrome 和 Safari 的开发者控制台或 Firebug)的 Network 选项栏。

为什么我在上传大文件时在上传结果中只得到一个空文件?(PHP)

你可能是因为服务端应用配置中设置了大文件限制。

在 PHP 目录的 .htaccess 文件中添加下列配置:

php_value upload_max_filesize 9G
php_value post_max_size 9G
php_value max_execution_time 200
php_value max_input_time 200
php_value memory_limit 256M

如果不起作用,直接修改 php.ini 中以下配置后重启 php 程序:

upload_max_filesize 9G
post_max_size 9G
max_execution_time 200
max_input_time 200
memory_limit 256M
上传带有非 ASCII 字符的文件是否有问题?(Windows Server 下的 PHP)

默认情况下,Linux 和 Windows 主机上的 PHP 只能处理 unicode 文件名。

有关如何在 Windows 服务器平台上处理 unicode 文件名的深入说明和建议,请参阅这篇文章:filesystem-encoding-and-php

为什么从服务端返回的非 ASCII 文件名会出现字符串校验失败?

这关系到你的服务端环境,你可能必须进行 Unicode 规范化,从而实现对 Unicode 字符串进行二进制转换。

该插件是否支持 HTTP 状态码?

FileUpload 插件在支持 XHR 文件上传的浏览器下可以正确处理响应的 HTTP 状态码。它甚至可以正确显示返回的错误消息,例如通过下面 HTTP header 返回的 "Error: Service Unavailable":

HTTP/1.0 503 Service Unavailable

但是,对于不支持 XHR 文件上传的浏览器(包括 IE10 之前的版本),将使用 Iframe 传输。而从一个 iframe 加载事件中是无法获得 HTTP 状态码的。

因此,即使服务端返回错误状态码,iframe 传输也只会为每一次上传触发 done 事件。不过,可以参考下列举例,通过解析响应的内容将其转化为触发 fail 事件:

// By default, the iFrame Transport handles all responses as success,
// so we override the iFrame to JSON converter to handle error responses:
$.ajaxSetup({
    converters: {
        'iframe json': function (iframe) {
            var result = iframe && $.parseJSON($(iframe[0].body).text());
            if (result.error) {
                // Handling JSON responses with error property:
                // {"error": "Upload failed"}
                throw result.error;
            }
            return result;
        }
    }
});

IE8 还有烦人的一点,如果你返回一个 HTTP 状态码不是 200 的错误响应(例如 INTERNAL_SERVER_ERROR),IE 会将 iframe 的内容替换为本地错误信息(res://ieframe.dll/http_500.htm)。

IE9 也会有问题,未定义 iframe 会导致回调失败。