Html 上传前调整图像大小 - 将画布转换为 File 对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15990946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resize image before upload - convert canvas to a File object
提问by Sfisioza
Here's the code fragment I'm using now to upload multiple images using HTML5 File API:
这是我现在使用 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);
}
}
I'd like to resize the images beforeupload using canvas object, but not having experience with this, I'm not sure how can update the code using techniques, e.g. the one described here: HTML5 Pre-resize images before uploading
我想在使用画布对象上传之前调整图像大小,但没有这方面的经验,我不确定如何使用技术更新代码,例如此处描述的技术:HTML5 Pre-resize images before uploading
canvas.toDataURL("image/png");
will return an encoded string. But I need to post the File
object.
canvas.toDataURL("image/png");
将返回一个编码字符串。但我需要发布File
对象。
Edit
编辑
How would you write (reasonably) cross browser function for most modern browsers to resize the File before upload, handling jpg,png and gifs with transparency:
您将如何为大多数现代浏览器编写(合理的)跨浏览器功能,以在上传之前调整文件大小,处理透明的 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){}
回答by Brendon John Wildbore
Try something like this:
尝试这样的事情:
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.");
};
}
Please note:
请注意:
Working with fileloaders and loading images means there are some delays and the function is therefore asynchronous so trying to simply return the blob data wont work. You need to wait for the loading to occur before you can use the loaded data and fire off a call to your upload function for EACH file.
使用文件加载器和加载图像意味着存在一些延迟,因此该函数是异步的,因此尝试简单地返回 blob 数据是行不通的。您需要等待加载发生,然后才能使用加载的数据并为每个文件调用上传函数。
Also fileloader may have some browser compatability issues but I don't think this is possible any other way client side.
此外,fileloader 可能有一些浏览器兼容性问题,但我认为这不可能以任何其他方式客户端。
回答by tfmontague
Client-side image resize
客户端图像调整大小
Option 1. Use the Pica library (https://github.com/nodeca/pica)
选项 1. 使用 Pica 库 ( https://github.com/nodeca/pica)
Option 2. Use the following custom script (http://jsfiddle.net/cL3hapL4/2/)
选项 2. 使用以下自定义脚本 ( http://jsfiddle.net/cL3hapL4/2/)
var file = document.getElementById('imageUpload');
var mime = "image/jpeg";
var max_width = 100;
var max_height = 100;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
// Clear canvas, and resize image
ctx.clearRect(0, 0, max_width, max_height);
ctx.drawImage(img,
0, 0, img.width, img.height, // size of image
0, 0, max_width, max_height // size of canvas
);
// Get image from canvas as a dataURI, and convert to a blob object
var dataURI = canvas.toDataUrl(mime);
// Note: This function can be replaced with canvas.toBlob(),
// once supported by browsers.
// ---
var image_blob = (function () {
var binary = atob(dataURI.split(',')[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: mime});
})();
// ---
// Attach blob-object (contains our image) to form object
var form = new Form();
form.append("image", image_blob);
// Send AJAX request with multi-part data
var xhr = new XMLHttpRequest();
xhr.open('POST', '/route', true);
xhr.send(form);
// jQuery version
//$.ajax({
// type: "POST",
// url: "/route",
// data: form,
// processData: false,
// contentType: false
//})
//.done(function (response) {
// console.log(response);
//});
};
img.src = URL.createObjectURL(file);
回答by Ray Nicholus
You can call toBlob
on the <canvas>
element. This will return a Blob
, which is the parent interface of File
. You can then send this object to your server via XHR2.
您可以调用toBlob
该<canvas>
元素。这将返回一个Blob
,它是 的父接口File
。然后您可以通过 XHR2 将此对象发送到您的服务器。