上传前调整图像大小 - 将画布转换为File对象

Sfi*_*oza 17 javascript html5 file-upload html5-canvas

这是我现在用来使用HTML5 File API上传多个图像的代码片段:

/**
 * @param {FileList} files
 */
upload: function(files){
    nfiles = files.length;

    for (var i = 0; i < nfiles; i++) {
        /** @var file File **/
        var file = files[i];

        var xhr = new XMLHttpRequest();

        xhr.open("POST", settings.post_upload, true);
        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        xhr.upload.filenumb = i;
        xhr.filenumb = i;
        xhr.upload.filename = file.name;

        var nef = new FormData();
        nef.append("folder", settings.folder);
        nef.append("file_element", settings.file_elem);
        nef.append("udata", settings.user_data);
        nef.append(settings.file_elem, file);
        xhr.send(nef);

    }
}
Run Code Online (Sandbox Code Playgroud)

我想使用canvas对象上传之前调整图像大小,但没有相关经验,我不知道如何使用技术更新代码,例如下面描述的那些:HTML5在上传之前预先调整图像大小

canvas.toDataURL("image/png");将返回一个编码的字符串.但是我需要发布这个File对象.

编辑

如何(合理地)为大多数现代浏览器编写跨浏览器功能,以便在上传之前调整文件大小,处理具有透明度的jpg,png和gif:

/** 
 * @param {File} file 
 * @param int max_width
 * @param int max_height
 * @param float compression_ratio
 * @returns File
 */
function resize(file, max_width, max_height, compression_ratio){}
Run Code Online (Sandbox Code Playgroud)

小智 25

尝试这样的事情:

function resize(file, max_width, max_height, compression_ratio, imageEncoding){
    var fileLoader = new FileReader(),
    canvas = document.createElement('canvas'),
    context = null,
    imageObj = new Image(),
    blob = null;            

    //create a hidden canvas object we can use to create the new resized image data
    canvas.id     = "hiddenCanvas";
    canvas.width  = max_width;
    canvas.height = max_height;
    canvas.style.visibility   = "hidden";   
    document.body.appendChild(canvas);  

    //get the context to use 
    context = canvas.getContext('2d');  

    // check for an image then
    //trigger the file loader to get the data from the image         
    if (file.type.match('image.*')) {
        fileLoader.readAsDataURL(file);
    } else {
        alert('File is not an image');
    }

    // setup the file loader onload function
    // once the file loader has the data it passes it to the 
    // image object which, once the image has loaded, 
    // triggers the images onload function
    fileLoader.onload = function() {
        var data = this.result; 
        imageObj.src = data;
    };

    fileLoader.onabort = function() {
        alert("The upload was aborted.");
    };

    fileLoader.onerror = function() {
        alert("An error occured while reading the file.");
    };  


    // set up the images onload function which clears the hidden canvas context, 
    // draws the new image then gets the blob data from it
    imageObj.onload = function() {  

        // Check for empty images
        if(this.width == 0 || this.height == 0){
            alert('Image is empty');
        } else {                

            context.clearRect(0,0,max_width,max_height);
            context.drawImage(imageObj, 0, 0, this.width, this.height, 0, 0, max_width, max_height);


            //dataURItoBlob function available here:
            // http://stackoverflow.com/questions/12168909/blob-from-dataurl
            // add ')' at the end of this function SO dont allow to update it without a 6 character edit
            blob = dataURItoBlob(canvas.toDataURL(imageEncoding));

            //pass this blob to your upload function
            upload(blob);
        }       
    };

    imageObj.onabort = function() {
        alert("Image load was aborted.");
    };

    imageObj.onerror = function() {
        alert("An error occured while loading image.");
    };

}
Run Code Online (Sandbox Code Playgroud)

请注意:

使用文件加载器和加载图像意味着有一些延迟,因此该函数是异步的,因此尝试简单地返回blob数据将无法工作.您需要等待加载发生后才能使用加载的数据并启动对EACH文件的上传功能的调用.

文件加载器也可能有一些浏览器兼容性问题,但我不认为这可能是客户端的任何其他方式.

  • 一般来说,这是有效的,但由于这是一个赏金,我会做两个笔记.首先,FileReader确实存在一些可用性问题:IE <10,Safari <current,android <3X(如果可以接受,可能会询问OP).其次,您应该在加载图像时添加一个onerror处理程序,以便在出现问题时重试/失败/警告并且在onload上确保测试零宽度/高度(加载成功时发生,但文件为空).经过这些改变,看起来还不错. (4认同)

Ray*_*lus 2

您可以调用toBlob<canvas>元素。这将返回 a Blob,它是 的父接口File。然后您可以通过 XHR2 将此对象发送到您的服务器。