[英]Sending image manipulated via JS in AJAX POST request
我是一个服务器端开发人员,正在学习香草JS的精髓。 我需要清除有关为我在JS中创建的图像对象发送Ajax POST请求的概念-这个问题就是关于此的。
想象一下一个网络应用程序,用户可以在其中上传照片供他人查看。 在上传每张图片时,我使用香草JS(通过解释幻数 )确认图片的mime类型,然后调整图片的大小以进行优化。
调整大小后,我执行以下操作:
var canvas = document.createElement('canvas');
canvas.width = resized_width;
canvas.height = resized_height;
var ctx = canvas.getContext("2d");
ctx.drawImage(source_img, 0, 0, resized_width, resized_height);
var resized_img = new Image();
resized_img.src = canvas.toDataURL("image/jpeg",0.7);
return resized_img;
返回的图像对象必须通过Ajax请求发送到后端。 就像是:
function overwrite_default_submit(e) {
e.preventDefault();
var form = new FormData();
form.append("myfile", resized_img, img_name);
var xhr = new XMLHttpRequest();
xhr.open('POST', e.target.action);
// xhr.send(form); // uncomment to really send the request
}
但是,调整大小后返回的图像对象本质上是一个HTML元素,例如<img src="data:image/jpeg;base64>
。而FormData
对象中期望的对象应该是File
对象,例如: File { name: "example.jpg", lastModified: 1500117303000, lastModifiedDate: Date 2017-07-15T11:15:03.000Z, webkitRelativePath: "", size: 115711, type: "image/jpeg" }
。
那我该怎么解决这个问题呢? 宁愿在这里学习最有效的做事方式。
顺便说一句,我已经看到了使用JS FILE对象的示例 ,但是鉴于最近 File
获得了Safari,Opera Mobile和内置Android浏览器的支持,我更喜欢跨浏览器的方法。
此外,只需要纯JS解决方案,因为我将其用作练习绳索的练习。 jQuery是我的雷达,但稍后。
我其余的代码如下(为简洁起见,仅包括JPEG处理):
var max_img_width = 400;
var wranges = [max_img_width, Math.round(0.8*max_img_width), Math.round(0.6*max_img_width),Math.round(0.4*max_img_width),Math.round(0.2*max_img_width)];
// grab the file from the input and process it
function process_user_file(e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = process_image;
reader.readAsArrayBuffer(file.slice(0,25));
}
// checking file type programmatically (via magic numbers), getting dimensions and returning a compressed image
function process_image(e) {
var img_width;
var img_height;
var view = new Uint8Array(e.target.result);
var arr = view.subarray(0, 4);
var header = "";
for(var i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
switch (header) {
case "ffd8ffe0":
case "ffd8ffe1":
case "ffd8ffe2":
case "ffd8ffe3":
case "ffd8ffe8":
// magic numbers represent type = "image/jpeg";
// use the 'slow' method to get the dimensions of the media
img_file = browse_image_btn.files[0];
var fr = new FileReader();
fr.onload = function(){
var dataURL = fr.result;
var img = new Image();
img.onload = function() {
img_width = this.width;
img_height = this.height;
resized_img = resize_and_compress(this, img_width, img_height, 80);
}
img.src = dataURL;
};
fr.readAsDataURL(img_file);
to_send = browse_image_btn.files[0];
load_rest = true;
subform.disabled = false;
break;
default:
// type = "unknown"; // Or one can use the blob.type as fallback
load_rest = false;
subform.disabled = true;
browse_image_btn.value = "";
to_send = null;
break;
}
}
// resizing (& compressing) image
function resize_and_compress(source_img, img_width, img_height, quality){
var new_width;
switch (true) {
case img_width < wranges[4]:
new_width = wranges[4];
break;
case img_width < wranges[3]:
new_width = wranges[4];
break;
case img_width < wranges[2]:
new_width = wranges[3];
break;
case img_width < wranges[1]:
new_width = wranges[2];
break;
case img_width < wranges[0]:
new_width = wranges[1];
break;
default:
new_width = wranges[0];
break;
}
var wpercent = (new_width/img_width);
var new_height = Math.round(img_height*wpercent);
var canvas = document.createElement('canvas');
canvas.width = new_width;
canvas.height = new_height;
var ctx = canvas.getContext("2d");
ctx.drawImage(source_img, 0, 0, new_width, new_height);
console.log(ctx);
var resized_img = new Image();
resized_img.src = canvas.toDataURL("image/jpeg",quality/100);
return resized_img;
}
更新:我正在使用以下内容:
// converting image data uri to a blob object
function dataURItoBlob(dataURI,mime_type) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); }
return new Blob([ab], { type: mime_type });
}
其中dataURI
参数为canvas.toDataURL(mime_type,quality/100)
请参阅此SO帖子: 如何从html图像获取base64编码的数据
我认为您需要调用“ canvas.toDataURL()”来获取图像的实际base64流。
var image = canvas.toDataURL();
然后使用表单上载它: 使用FormData上载base64编码的图像?
var data = new FormData();
data.append("image_data", image);
未经测试,但这应该是关于它。
您应该调用canvas.toBlob()来获取二进制文件,而不是使用base64字符串。
它是异步的,因此您必须为其添加回调。
canvas.toBlob(function(blob) {
resized_img.onload = function() {
// no longer need to read the blob so it's revoked
URL.revokeObjectURL(this.url);
};
// Preview the image using createObjectURL
resized_img.src = URL.createObjectURL(blob);
// Attach the blob to the FormData
var form = new FormData();
form.append("myfile", blob, img_name);
}, "image/jpeg", 0.7);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.