我将版本 1:标准 html 文件上传与版本 2:html5 fileApi 和 ajax 上传进行了比较。结果发现html5的fileApi和ajax上传比老的html文件上传慢了很多。
- 为什么版本 2 的上传速度比版本 1 慢很多?
- 如何在版本 2 中加速上传?
版本 1:
HTML
<g:form method="post" accept-charset="utf-8" enctype="multipart/form-data"
name="imageUploaderForm" id="imageUploaderForm" url="someurl">
<input type="file" accept="image/jpeg, image/gif, image/png"
name="image" id="image" />
</form>
JS(我用 JQueryForm )
$("#image").change(function() {
$("#imageUploaderForm").ajaxForm({
complete: function(response){
console.log("upload complete");
}
});
$("#imageUploaderForm").submit();
});
服务器代码 Grails 2.2.4:
CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image')
byte [] imageBytes = file.getBytes()
版本 2:
HTML
<g:form method="post" accept-charset="utf-8" enctype="multipart/form-data"
name="imageUploaderForm" id="imageUploaderForm" url="someurl"></form>
<input id="UploadFileInput" class="UploadFileInput" type="file" name="image" accept="image/jpeg, image/gif, image/png" />
JS(我使用 filereader.js,它只是包装了 jquery 的文件读取器 api)我将上传的图像加载到 html5 Canvas 中,因为我需要在上传之前操作图像。
var fileReaderOpts = {
readAsDefault: 'BinaryString',
on: {
load: function(event, file) {
var $img = $('<img>'),
imgWidth, imgHeight;
$img.load(function() {
// Create the canvas.
$originalCanvas = $('<canvas data-caman-hidpi-disabled>');
var originalContext = $originalCanvas[0].getContext('2d');
// Save image to canvas
$originalCanvas[0].width = this.width;
$originalCanvas[0].height = this.height;
originalContext.drawImage(this, 0, 0);
// some image modification on the canvas
// send image to server
var imageUrl = $originalCanvas[0].toDataURL();
$("#imageUploaderForm").ajaxForm({
data: {
img : imageUrl,
},
complete: function(response){
console.log("upload complete");
}
});
$("#imageUploaderForm").submit();
}); // end $img.load
// Set the src of the img, which will trigger the load event when done
$img.attr('src', event.target.result);
},// end load
beforestart: function(file) {
// Accept only images. Returning false will reject the file.
return /^image/.test(file.type);
}
}
};
// Bind the fileReader plugin the upload input and the drop area.
$("UploadFileInput").fileReaderJS(fileReaderOpts);
服务器代码 Grails 2.2.4:
String imgBase64 = params.image
imgBase64 = imgBase64.trim().replaceFirst("data:image/png;base64,", "")
byte[] imageBytes = Base64.decode(imgBase64.getBytes())
这是我测量的结果:
我已经上传了一个 7.5MB 大小的 jpg 图片,包括版本 1 和版本 2,还有 pinterest 和 flickr。在提交表单时在客户端处理完图像后,我启动了版本 1 和版本 2 的计时器。
注意:canvas相关的代码不在时间之内。之后我开始测量。
结果:
- 版本 1:1.16 分钟
- 版本 2:3.43 分钟
- pinterest:1.09 分钟
- flickr:1.11 分钟
最佳答案
版本 2 Base64 对 toDataUrl() 中的数据进行编码。与仅发送原始二进制文件的版本 1 相比,这将是通过网络发送的更多数据。要看到这一点,请使用 Fiddler 观察 HTTP 流量并比较两者。 Statistics 选项卡将向您显示“已发送的字节数”,我认为在您的第 2 版方法中会更多。测量时,请小心开始和停止计时器的位置。我知道您在评论中说您排除了 Canvas 工作,但除非您是从 after toDataUrl() 直到完全触发进行测量,否则这不是网络时间的“公平”比较。简而言之,它变慢是因为 a) 您要发送更多数据,并且 b) toDataUrl 必须将图像从 Canvas 复制到表单。
至于如何使其更快,要做到这一点并保持您的功能有点棘手。你在客户端做更多的工作,所以它必然会变慢。 AFAIK, Canvas 没有办法将数据作为原始字节(不是 base64)流式传输到服务器,这正是您想要的。 jQuery File Upload 至少可以帮助它变得更加用户友好,或者可能有一些魔力我不清楚除了 base64 之外还可以通过某种方式发送数据:https://github.com/blueimp/jQuery-File-Upload/wiki/Client-side-Image-Resizing .
根据您在 Canvas 中所做的事情和您的服务器资源,在服务器上进行图像处理可能更有意义。这肯定会使上传速度更快,但会占用服务器 CPU 和内存。
关于javascript - HTML5 文件上传速度慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19030451/