上传前使用HTML5调整图像大小

我发现了几个不同的post,甚至在回答这个问题的stackoverflow上的问题。 我基本上实现这个职位相同的东西。

所以这是我的问题。 当我上传照片时,我还需要提交表格的其余部分。 这是我的html:

<form id="uploadImageForm" enctype="multipart/form-data"> <input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos(\'#{imageUploadUrl}\')" /> <input id="name" value="#{name}" /> ... a few more inputs ... </form> 

以前,我不需要调整图像大小,所以我的javascript看起来像这样:

 window.uploadPhotos = function(url){ var data = new FormData($("form[id*='uploadImageForm']")[0]); $.ajax({ url: url, data: data, cache: false, contentType: false, processData: false, type: 'POST', success: function(data){ ... handle error... } } }); }; 

这一切都很好…现在我需要调整图像…我怎样才能更换窗体中的图像,以便resize的张贴,而不是上传的图像?

 window.uploadPhotos = function(url){ var resizedImage; // Read in file var file = event.target.files[0]; // Ensure it's an image if(file.type.match(/image.*/)) { console.log('An image has been loaded'); // Load the image var reader = new FileReader(); reader.onload = function (readerEvent) { var image = new Image(); image.onload = function (imageEvent) { // Resize the image var canvas = document.createElement('canvas'), max_size = 1200, width = image.width, height = image.height; if (width > height) { if (width > max_size) { height *= max_size / width; width = max_size; } } else { if (height > max_size) { width *= max_size / height; height = max_size; } } canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(image, 0, 0, width, height); resizedImage = canvas.toDataURL('image/jpeg'); } image.src = readerEvent.target.result; } reader.readAsDataURL(file); } // TODO: Need some logic here to switch out which photo is being posted... var data = new FormData($("form[id*='uploadImageForm']")[0]); $.ajax({ url: url, data: data, cache: false, contentType: false, processData: false, type: 'POST', success: function(data){ ... handle error... } } }); }; 

我想过移动文件input的forms,并有一个隐藏的inputforms,我把价值的大小调整后的图像的值…但我想知道如果我可以只是将图像已经在表格中了。

这是我最终做的,它运作得很好。

首先,我移动了表单之外的文件input,以便它不被提交:

 <input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos(\'#{imageUploadUrl}\')" /> <form id="uploadImageForm" enctype="multipart/form-data"> <input id="name" value="#{name}" /> ... a few more inputs ... </form> 

然后,我改变了uploadPhotosfunction只处理大小调整:

 window.uploadPhotos = function(url){ // Read in file var file = event.target.files[0]; // Ensure it's an image if(file.type.match(/image.*/)) { console.log('An image has been loaded'); // Load the image var reader = new FileReader(); reader.onload = function (readerEvent) { var image = new Image(); image.onload = function (imageEvent) { // Resize the image var canvas = document.createElement('canvas'), max_size = 544,// TODO : pull max size from a site config width = image.width, height = image.height; if (width > height) { if (width > max_size) { height *= max_size / width; width = max_size; } } else { if (height > max_size) { width *= max_size / height; height = max_size; } } canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(image, 0, 0, width, height); var dataUrl = canvas.toDataURL('image/jpeg'); var resizedImage = dataURLToBlob(dataUrl); $.event.trigger({ type: "imageResized", blob: resizedImage, url: dataUrl }); } image.src = readerEvent.target.result; } reader.readAsDataURL(file); } }; 

正如你所看到的,我正在使用canvas.toDataURL('image/jpeg'); 改变大小的图像到一个dataUrl,然后我调用函数dataURLToBlob(dataUrl); 把dataUrl转换成一个blob,然后我可以将它添加到表单中。 当blob被创build时,我触发一个自定义事件。 这里是创buildblob的函数:

 /* Utility function to convert a canvas to a BLOB */ var dataURLToBlob = function(dataURL) { var BASE64_MARKER = ';base64,'; if (dataURL.indexOf(BASE64_MARKER) == -1) { var parts = dataURL.split(','); var contentType = parts[0].split(':')[1]; var raw = parts[1]; return new Blob([raw], {type: contentType}); } var parts = dataURL.split(BASE64_MARKER); var contentType = parts[0].split(':')[1]; var raw = window.atob(parts[1]); var rawLength = raw.length; var uInt8Array = new Uint8Array(rawLength); for (var i = 0; i < rawLength; ++i) { uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], {type: contentType}); } /* End Utility function to convert a canvas to a BLOB */ 

最后,这里是我的事件处理程序,它从自定义事件中获取blob,附加表单然后提交它。

 /* Handle image resized events */ $(document).on("imageResized", function (event) { var data = new FormData($("form[id*='uploadImageForm']")[0]); if (event.blob && event.url) { data.append('image_data', event.blob); $.ajax({ url: event.url, data: data, cache: false, contentType: false, processData: false, type: 'POST', success: function(data){ //handle errors... } }); } }); 

如果有兴趣,我已经做了一个打字稿版本:

 interface IResizeImageOptions { maxSize: number; file: File; } const resizeImage = (settings: IResizeImageOptions) => { const file = settings.file; const maxSize = settings.maxSize; const reader = new FileReader(); const image = new Image(); const canvas = document.createElement('canvas'); const dataURItoBlob = (dataURI: string) => { const bytes = dataURI.split(',')[0].indexOf('base64') >= 0 ? atob(dataURI.split(',')[1]) : unescape(dataURI.split(',')[1]); const mime = dataURI.split(',')[0].split(':')[1].split(';')[0]; const max = bytes.length; const ia = new Uint8Array(max); for (var i = 0; i < max; i++) ia[i] = bytes.charCodeAt(i); return new Blob([ia], {type:mime}); }; const resize = () => { let width = image.width; let height = image.height; if (width > height) { if (width > maxSize) { height *= maxSize / width; width = maxSize; } } else { if (height > maxSize) { width *= maxSize / height; height = maxSize; } } canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(image, 0, 0, width, height); let dataUrl = canvas.toDataURL('image/jpeg'); return dataURItoBlob(dataUrl); }; return new Promise((ok, no) => { if (!file.type.match(/image.*/)) { no(new Error("Not an image")); return; } reader.onload = (readerEvent: any) => { image.onload = () => ok(resize()); image.src = readerEvent.target.result; }; reader.readAsDataURL(file); }) }; 

这里是JavaScript的结果:

 var resizeImage = function (settings) { var file = settings.file; var maxSize = settings.maxSize; var reader = new FileReader(); var image = new Image(); var canvas = document.createElement('canvas'); var dataURItoBlob = function (dataURI) { var bytes = dataURI.split(',')[0].indexOf('base64') >= 0 ? atob(dataURI.split(',')[1]) : unescape(dataURI.split(',')[1]); var mime = dataURI.split(',')[0].split(':')[1].split(';')[0]; var max = bytes.length; var ia = new Uint8Array(max); for (var i = 0; i < max; i++) ia[i] = bytes.charCodeAt(i); return new Blob([ia], { type: mime }); }; var resize = function () { var width = image.width; var height = image.height; if (width > height) { if (width > maxSize) { height *= maxSize / width; width = maxSize; } } else { if (height > maxSize) { width *= maxSize / height; height = maxSize; } } canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(image, 0, 0, width, height); var dataUrl = canvas.toDataURL('image/jpeg'); return dataURItoBlob(dataUrl); }; return new Promise(function (ok, no) { if (!file.type.match(/image.*/)) { no(new Error("Not an image")); return; } reader.onload = function (readerEvent) { image.onload = function () { return ok(resize()); }; image.src = readerEvent.target.result; }; reader.readAsDataURL(file); }); }; 

用法如下:

 resizeImage({ file: $image.files[0], maxSize: 500 }).then(function (resizedImage) { console.log("upload resized image") }).catch(function (err) { console.error(err); }); 

或( async / await ):

 const config = { file: $image.files[0], maxSize: 500 }; const resizedImage = await resizeImage(config) console.log("upload resized image")