在上传到服务器之前,使用 JavaScript 在客户端调整图像大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2434458/
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
Image resizing client-side with JavaScript before upload to the server
提问by geraud
I am looking for a way to resize an image client-side with JavaScript (really resize, not just change width and height).
I know it's possible to do it in Flash but I would like to avoid it if possible.
我正在寻找一种使用 JavaScript 调整图像客户端大小的方法(真正调整大小,而不仅仅是更改宽度和高度)。
我知道可以在 Flash 中执行此操作,但如果可能,我想避免使用它。
Is there any open source algorithm somewhere on the web?
网络上有什么开源算法吗?
回答by dcollien
Here's a gist which does this: https://gist.github.com/dcollien/312bce1270a5f511bf4a
这是执行此操作的要点:https: //gist.github.com/dcollien/312bce1270a5f511bf4a
(an es6 version, and a .js version which can be included in a script tag)
(一个 es6 版本和一个 .js 版本,可以包含在脚本标签中)
You can use it as follows:
您可以按如下方式使用它:
<input type="file" id="select">
<img id="preview">
<script>
document.getElementById('select').onchange = function(evt) {
ImageTools.resize(this.files[0], {
width: 320, // maximum width
height: 240 // maximum height
}, function(blob, didItResize) {
// didItResize will be true if it managed to resize it, otherwise false (and will return the original file as 'blob')
document.getElementById('preview').src = window.URL.createObjectURL(blob);
// you can also now upload this blob using an XHR.
});
};
</script>
It includes a bunch of support detection and polyfills to make sure it works on as many browsers as I could manage.
它包括一堆支持检测和 polyfills,以确保它在我能管理的尽可能多的浏览器上工作。
(it also ignores gif images - in case they're animated)
(它也会忽略 gif 图像 - 如果它们是动画的)
回答by Jeremy Usher
The answer to this is yes - in HTML 5 you can resize images client-side using the canvas element. You can also take the new data and send it to a server. See this tutorial:
答案是肯定的 - 在 HTML 5 中,您可以使用 canvas 元素在客户端调整图像大小。您还可以获取新数据并将其发送到服务器。请参阅本教程:
http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
回答by ignacio
If you were resizing before uploading I just found out this http://www.plupload.com/
如果您在上传之前调整大小,我刚刚发现这个 http://www.plupload.com/
It does all the magic for you in any imaginable method.
它以任何可以想象的方法为您带来所有魔力。
Unfortunately HTML5 resize only is supported with Mozilla browser, but you can redirect other browsers to Flash and Silverlight.
不幸的是,只有 Mozilla 浏览器支持 HTML5 调整大小,但您可以将其他浏览器重定向到 Flash 和 Silverlight。
I just tried it and it worked with my android!
我刚刚尝试过,它与我的 android 一起工作!
I was using http://swfupload.org/in flash, it does the job very well, but the resize size is very small. (cannot remember the limit) and does not go back to html4 when flash is not available.
我在 flash中使用http://swfupload.org/,它的工作非常好,但调整大小非常小。(不记得限制了)并且在 flash 不可用时不会回到 html4。
回答by Vitaly
http://nodeca.github.io/pica/demo/
http://nodeca.github.io/pica/demo/
In modern browser you can use canvas to load/save image data. But you should keep in mind several things if you resize image on the client:
在现代浏览器中,您可以使用画布来加载/保存图像数据。但是,如果您在客户端调整图像大小,则应记住以下几点:
- You will have only 8bits per channel (jpeg can have better dynamic range, about 12 bits). If you don't upload professional photos, that should not be a problem.
- Be careful about resize algorithm. The most of client side resizers use trivial math, and result is worse than it could be.
- You may need to sharpen downscaled image.
- If you wish do reuse metadata (exif and other) from original - don't forget to strip color profile info. Because it's applied when you load image to canvas.
- 每个通道只有 8 位(jpeg 可以有更好的动态范围,大约 12 位)。如果您不上传专业照片,那应该不是问题。
- 小心调整大小算法。大多数客户端调整器使用微不足道的数学,结果比预期的更糟。
- 您可能需要锐化缩小的图像。
- 如果您希望重用原始元数据(exif 和其他) - 不要忘记去除颜色配置文件信息。因为它在您将图像加载到画布时应用。
回答by David V.
Perhaps with the canvas tag (though it's not portable). There's a blog about how to rotate an image with canvas here, I suppose if you can rotate it, you can resize it. Maybe it can be a starting point.
也许使用画布标签(尽管它不可移植)。有一个关于如何使用画布旋转图像的博客here,我想如果你可以旋转它,你可以调整它的大小。也许它可以是一个起点。
See this libraryalso.
另请参阅此库。
回答by Gabriel Ambrósio Archanjo
You can use a javascript image processing framework for client-side image processing before uploading the image to the server.
在将图像上传到服务器之前,您可以使用 javascript 图像处理框架进行客户端图像处理。
Below I used MarvinJto create a runnable code based on the example in the following page: "Processing images in client-side before uploading it to a server"
下面我使用MarvinJ根据以下页面中的示例创建了一个可运行的代码: “在将图像上传到服务器之前在客户端处理图像”
Basically I use the method Marvin.scale(...)to resize the image. Then, I upload the image as a blob (using the method image.toBlob()). The server answers back providing a URL of the received image.
基本上我使用Marvin.scale(...)方法来调整图像大小。然后,我将图像作为 blob 上传(使用方法image.toBlob())。服务器回复提供接收图像的 URL。
/***********************************************
* GLOBAL VARS
**********************************************/
var image = new MarvinImage();
/***********************************************
* FILE CHOOSER AND UPLOAD
**********************************************/
$('#fileUpload').change(function (event) {
form = new FormData();
form.append('name', event.target.files[0].name);
reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
reader.onload = function(){
image.load(reader.result, imageLoaded);
};
});
function resizeAndSendToServer(){
$("#divServerResponse").html("uploading...");
$.ajax({
method: 'POST',
url: 'https://www.marvinj.org/backoffice/imageUpload.php',
data: form,
enctype: 'multipart/form-data',
contentType: false,
processData: false,
success: function (resp) {
$("#divServerResponse").html("SERVER RESPONSE (NEW IMAGE):<br/><img src='"+resp+"' style='max-width:400px'></img>");
},
error: function (data) {
console.log("error:"+error);
console.log(data);
},
});
};
/***********************************************
* IMAGE MANIPULATION
**********************************************/
function imageLoaded(){
Marvin.scale(image.clone(), image, 120);
form.append("blob", image.toBlob());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
<form id="form" action='/backoffice/imageUpload.php' style='margin:auto;' method='post' enctype='multipart/form-data'>
<input type='file' id='fileUpload' class='upload' name='userfile'/>
</form><br/>
<button type="button" onclick="resizeAndSendToServer()">Resize and Send to Server</button><br/><br/>
<div id="divServerResponse">
</div>
回答by Tatarize
Yes, with modern browsers this is totally doable. Even doable to the point of uploading the file specifically as a binary file having done any number of canvas alterations.
是的,使用现代浏览器,这是完全可行的。甚至可以将文件专门作为已完成任意数量画布更改的二进制文件上传。
(this answer is a improvement of the accepted answer here)
(此答案是对此处已接受答案的改进)
Keeping in mind to catch process the result submission in the PHP with something akin to:
请记住,在 PHP 中使用类似于以下内容的方法来捕获处理结果提交:
//File destination
$destination = "/folder/cropped_image.png";
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);
If one worries about Vitaly's point, you can try some of the cropping and resizing on the working jfiddle.
如果有人担心 Vitaly 的观点,您可以尝试对工作 jfiddle 进行一些裁剪和调整大小。
回答by xarlymg89
In my experience, this example has been the best solution for uploading a resized picture: https://zocada.com/compress-resize-images-javascript-browser/
根据我的经验,此示例是上传调整大小图片的最佳解决方案:https: //zocada.com/compress-resize-images-javascript-browser/
It uses the HTML5 Canvas feature.
它使用 HTML5 Canvas 功能。
The code is as 'simple' as this:
代码就像这样“简单”:
compress(e) {
const fileName = e.target.files[0].name;
const reader = new FileReader();
reader.readAsDataURL(e.target.files[0]);
reader.onload = event => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const elem = document.createElement('canvas');
const width = Math.min(800, img.width);
const scaleFactor = width / img.width;
elem.width = width;
elem.height = img.height * scaleFactor;
const ctx = elem.getContext('2d');
// img.width and img.height will contain the original dimensions
ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
ctx.canvas.toBlob((blob) => {
const file = new File([blob], fileName, {
type: 'image/jpeg',
lastModified: Date.now()
});
}, 'image/jpeg', 1);
},
reader.onerror = error => console.log(error);
};
}
There's only one downside with this option, and it's related with the image rotation, due to ignoring EXIF data. Which I'm working on at the moment. Will update after I'm done with that.
由于忽略了 EXIF 数据,此选项只有一个缺点,它与图像旋转有关。我目前正在做的工作。我做完之后会更新。
Another downside, is the lack of support foe IE/Edge, which I'm working on as well. Although there's information in the above link. For both of the issues.
另一个缺点是缺乏对 IE/Edge 的支持,我也在努力。虽然上面的链接中有信息。对于这两个问题。

