3

我比较了 VERSION1:标准 html 文件上传与 VERSION2:html5 fileApi 和 ajax 上传。事实证明,html5 fileApi 和 ajax 上传比旧的 html 文件上传慢很多。

  1. 为什么版本 2 的上传速度比版本 1 慢很多?
  2. 如何在 version2 中加速上传?

版本 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 包装了 filereader api)我将上传的图像加载到 html5 画布中,因为我需要在上传之前操作图像。

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。在提交表单的那一刻,在客户端处理完图像后,我启动了 version1 和 version2 的计时器。

注意:画布相关代码不包含在时间中。在此之后我开始测量。

结果:

  • 版本 1:1.16 分钟
  • 版本 2:3.43 分钟
  • 兴趣:1.09 分钟
  • flickr:1.11 分钟
4

1 回答 1

1

版本 2 Base64 对 toDataUrl() 中的数据进行编码。这将比版本 1 发送更多的数据,版本 1 只是发送原始二进制文件。要查看这一点,请使用 Fiddler 观察 HTTP 流量并比较两者。统计选项卡将向您显示“发送的字节数”,我认为您的版本 2 方法会更多。测量时,请注意启动和停止计时器的位置。我知道您在评论中说您排除了画布工作,但除非您从 toDataUrl() 之后直到完全触发进行测量,否则不是网络时间的“公平”比较。简而言之,它比较慢,因为 a)您要发送更多数据 b)toDataUrl 必须将图像从画布复制到表单。

至于如何让它更快,这有点棘手,要保留你的功能。你在客户端上做更多的工作,所以它必然会变慢。AFAIK,canvas 没有办法将数据作为原始字节(不是 base64)流式传输到服务器,这是您想要的。jQuery File Upload 至少可以帮助使其更加用户友好,或者可能有一些魔力,我不清楚除了 base64 以外的方式发送数据:https ://github.com/blueimp/jQuery-File-Upload/ wiki/客户端图像大小调整

根据您在画布和服务器资源中所做的事情,在服务器上进行图像处理可能更有意义。这肯定会使上传速度更快,但会牺牲服务器 CPU 和内存。

于 2013-09-26T15:18:27.853 回答