Here is my code i just want to download this image in specific folder or path on client side but it will downloaded in c/user/downloads I just want to download in F:/data/image how can I do this.
var svg = document.querySelector("svg");
var svgData = new XMLSerializer().serializeToString(svg);
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.setAttribute("src", "data:image/svg+xml;base64," + btoa(svgData));
img.onload = function () {
//canvas.width = 1200;
//canvas.height = 1200;
ctx.drawImage(img, 0, 0);
// Now is done
console.log(canvas.toDataURL("image/png"));
var jpegFile = canvas.toDataURL("image/jpeg");
function base64ToBlob(base64, mime) {
mime = mime || '';
var sliceSize = 1024;
var byteChars = window.atob(base64);
var byteArrays = [];
for (var offset = 0, len = byteChars.length; offset < len; offset += sliceSize) {
var slice = byteChars.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, { type: mime });
}
var jpegFile64 = jpegFile.replace(/^data:image\/(png|jpeg);base64,/, "");
var jpegBlob = base64ToBlob(jpegFile64, 'image/jpeg');
console.log(jpegBlob);
var a = document.createElement('a');
a.target = "patternImg/image.jpeg";
a.download = "image.jpeg";
a.href = canvas.toDataURL('image/jpeg');
document.body.appendChild(a);
a.click();
}
}
The browser security model does not allow code on the page to arbitrarily write to the file system. You need the user to interact with a "Save As..." dialog for that behaviour.
So you cannot do it without user interaction.
Related
I'm currently trying to convert a base64Encoded string (representation of an image) into an ImageData object in Javascript. However, this comes back with an error:
Uncaught InvalidStateError: Failed to construct 'ImageData': The input data length is not a multiple of 4.
The encoded image is 940 x 740
What am I missing? Any help appreciated
JSFiddle link with full code
function _base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
const base64String = ""; //truncated because stackoverflow question too long.
const arrBuffer = _base64ToArrayBuffer (base64String );
var array = new Uint8ClampedArray(arrBuffer);
console.log(array);
var image = new ImageData(array, 900, 740);
console.log(image);
You can get the ImageData from a Canvas
function _base64ToImageData(buffer, width, height) {
return new Promise(resolve => {
var image = new Image();
image.addEventListener('load', function (e) {
var canvasElement = document.createElement('canvas');
canvasElement.width = width;
canvasElement.height = height;
var context = canvasElement.getContext('2d');
context.drawImage(e.target, 0, 0, width, height);
resolve(context.getImageData(0, 0, width, height));
});
image.src = 'data:image/png;base64,' + buffer;
document.body.appendChild(image);
setTimeout(() => {
document.body.removeChild(image);
}, 1);
});
}
window.addEventListener('load', () => {
_base64ToImageData(base64String, 2056, 1236).then(data => {
console.log(data);
});
});
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
Here's a bit about function:
This function takes the file object from html input tag and according to the quality value passed it compresses the image on the browser itself and this compressed image is used to upload to the server. the problem here is that I am not able to return the compressed file object which is generated inside a callback function passed into eventlistner in the following code.
Here's the function definition:
function compress_image_file(image_file_object, quality) {
const file = image_file_object;
const file_name = file.name.replace(/\.[^/.]+$/, "");
var data_url = '';
const reader = new FileReader();
reader.readAsDataURL(file);
if (reader.readyState == 2) {
console.log('readyState = 2');
}
reader.addEventListener("load", function () {
//convert file to base 64 string
data_url = reader.result;
//create a temp image
image = new Image();
image.src = data_url;
//calculate new sizes for the new image
new_width = image.width * quality / 100;
new_height = image.height * quality / 100;
//create a canvas
canvas = document.createElement("canvas");
//setting canvas size
canvas.width = new_width;
canvas.height = new_height;
ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, new_width, new_height);
//convert new image to data url
newDataUrl = canvas.toDataURL();
//convert data url to file
var arr = newDataUrl.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var ext = '.' + mime.split('/')[1];
//decode the base-64 image
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var new_file = new File([u8arr], file_name + ext, { type: mime });
})
// I am trying to return the value of new_file
}
here is how I want to implement the above function
var file_object = input.files[0]
var new_file = compress_image_file(file_object, 50)
console.log(new_file) // undefined
instead of undefined how can I get the file object in var new_file
You cannot return a value from an event listener. You can promisefy your FileReader and return the value from it.
async function compress_image_file(image_file_object, quality) {
try {
const file = image_file_object;
const file_name = file.name.replace(/\.[^/.]+$/, "");
var data_url = "";
const reader = new FileReader();
reader.readAsDataURL(file);
//convert file to base 64 string
data_url = await readFile(file);
//create a temp image
image = new Image();
image.src = data_url;
//calculate new sizes for the new image
new_width = (image.width * quality) / 100;
new_height = (image.height * quality) / 100;
//create a canvas
canvas = document.createElement("canvas");
//setting canvas size
canvas.width = new_width;
canvas.height = new_height;
ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, new_width, new_height);
//convert new image to data url
newDataUrl = canvas.toDataURL();
//convert data url to file
var arr = newDataUrl.split(",");
var mime = arr[0].match(/:(.*?);/)[1];
var ext = "." + mime.split("/")[1];
//decode the base-64 image
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var new_file = new File([u8arr], file_name + ext, { type: mime });
//return the value of new_file
return new_file;
} catch (err) {
throw new Error(err);
}
}
function readFile(file) {
return new Promise((resolve, reject) => {
var fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = () => {
resolve(fr.result);
};
fr.onerror = reject;
});
}
var file_object = input.files[0];
compress_image_file(file_object, 50)
.then(new_file => {
console.log(new_file);
})
.catch(console.log);
Need help with my function to download a PNG from a SVG.
I read many similar post about that but don't succeed to apply to my code.
The image that I download is empty ...
My code :
function downloadCarteJPEG(nom,dpi) {
var svg = document.querySelector("svg");
var svgData = "";
if (typeof window.XMLSerializer != "undefined") {
svgData = (new XMLSerializer()).serializeToString(svg);
} else {
console.error("XMLSerializer undefined");
return;
}
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width * dpi / 25.4;
canvas.height = svgSize.height * dpi / 25.4;
var data = btoa(unescape(encodeURIComponent(svgData)));
data = 'data:image/svg+xml;base64,' + data;
var image = document.createElement("img");
image.onload = function() {
ctx.drawImage(image, 0, 0);
var link = document.createElement("a");
link.download = nom;
link.href = canvas.toDataURL("image/png");
document.querySelector("body").appendChild(link);
link.click();
document.querySelector("body").removeChild(link);
};
image.src = data;
console.log("EXIT");
}
Working on a web app, I have image files going directly to the S3 bucket from the browser. This works well in Chrome, but in Safari there are no errors, but the code ends up uploading an empty file to the S3 bucket. Everything basically looks like it works in Safari, the S3 server even returns a 204 successful http response, and the file looks like it is in the bucket (but has a size of 0 bytes).
I debugging, and the blobData has size 55747 in Chrome but only size 47560 in Safari for the same image. Also, I have found what looks slightly different is in the networking section dev tools:
Chrome - working (204 response has positive size ~ 534B):
Safari - not working with empty file ( size column shows just a dash line )
Here is the JS upload code:
function uploadFile(data_url, s3Data, url, filename, id, thumbnail_url){
var xhr = new XMLHttpRequest();
xhr.open("POST", s3Data.url);
var postData = new FormData();
for(key in s3Data.fields){
postData.append(key, s3Data.fields[key]);
}
var blobData = dataURItoBlob(data_url);
postData.append('file', new File([blobData], filename));
xhr.onreadystatechange = function() {
if(xhr.readyState === 4){
if(xhr.status === 200 || xhr.status === 204){
setTimeout(function(){
$('#photo_container').append('<div id="image_container_'+id+'" class="hover-card mdl-cell--3-col-desktop mdl-cell--2-col-tablet mdl-cell--2-col-phone mdl-shadow--2dp"></div>');
$('.star-image').unbind('click').click( star_image_click );
$('.close-image').unbind('click').click(remove_image_click);
loading_files -= 1;
if ( loading_files == 0 ) {
$('#photo_load_spinner').removeClass('is-active');
$('#photo_load_text').text("");
}else{
$('#photo_load_text').text(loading_files+" files loading. Please wait.");
}
}, 1000);
}else{
alert("Could not upload file. "+xhr.responseText);
}
}
};
xhr.send(postData);
}
function dataURItoBlob(dataURI) {
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: 'image/png'});
}
I am kind of at a loss as to what to look for next. Any help would be greatly appreciated. Thanks!
EDIT
Just figure I should give a little more information. The data_url is generated from a canvas element which I use to resize the image in the browser, although I have confirmed that the canvas shows the image correctly in safari before upload. Here is that code:
function ResizeFile(raw_file) {
var reader = new FileReader();
reader.onload = function(e) {
var img = document.createElement("img");
img.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
//ctx.drawImage(img, 0, 0);
var MAX = 1200;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX) {
height *= MAX / width;
width = MAX;
}
} else {
if (height > MAX) {
width *= MAX / height;
height = MAX;
}
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, width, height);
var dataurl = canvas.toDataURL("image/png");
getSignedRequest(dataurl);
}
img.src = e.target.result;
}
reader.readAsDataURL(raw_file);
}
We could resize image file and upload to server. Tested on Chrome and Safari, both works fine.
fileChange() {
var fileInputTag = document.getElementById("myFile");
if ('files' in fileInputTag) {
if (fileInputTag.files.length > 0) {
var file = fileInputTag.files[0];
var type = 'image/jpeg',
maxWidth = 800,
maxHeight = 600,
quality = 0.5,
ratio = 1,
canvas = document.createElement('canvas'),
context = canvas['getContext']('2d'),
canvasCopy = document.createElement('canvas'),
copyContext = canvasCopy.getContext('2d'),
img = new Image();
img.onload = function () {
if (img.width > maxWidth) {
ratio = maxWidth / img.width;
} else if (img.height > maxHeight) {
ratio = maxHeight / img.height;
}
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
context.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => {
blob['name'] = file.name.split('.')[0] + '.jpeg';
var formData:FormData = new FormData();
formData.append('uploadFile', blob, blob.name);
// do upload here
}, type, quality);
};
img.src = URL.createObjectURL(file);
}
}
}
Add this to index.html or execute it before above script execution
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
len = binStr.length,
arr = new Uint8Array(len);
for (var i = 0; i < len; i++ ) {
arr[i] = binStr.charCodeAt(i);
}
callback( new Blob( [arr], {type: type || 'image/png'} ) );
}
});
}
I remember Safari having limited support for FormData objects, for example:
https://developer.mozilla.org/en-US/docs/Web/API/FormData/set
https://developer.mozilla.org/en-US/docs/Web/API/FormData/get
I'm trying to resize an uploaded image, set it back to the input element before submitting.
$("#upload_button").click(function(){
var imgToUpload = document.getElementById('id_picture').files;
for (var x = 0; x < imgToUpload.length; x ++){
var getImg = imgToUpload[x];
console.log(typeof getImg);
if (! imgToUpload[x].type.match(/image.*/)){
alert("not an image");
return false;
}
var img = document.createElement("img");
img.src = window.URL.createObjectURL(getImg);
var canvas = document.createElement("canvas");
canvas.width = 20;
canvas.height = 20;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, 20, 20);
var resizedUrl = canvas.toDataURL("image/jpeg",0.7);
var byteString = atob(resizedUrl.split(",")[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var index = 0; index < byteString.length; index++){
ia[index] = byteString.charCodeAt(index);
}
var bob = new Blob([ab], {"type": getImg.type});
var p = document.getElementById('id_picture');
p.value = bob;
$("#upload_form").submit();
}
});
when i reach the p.value = bob, i will encounter the mentioned problem. Am i doing it wrong?
(i read that i can simply use canvas.toDataURL and set it to another hidden input, but I'm trying to see if this is possible)
You can use toDataURL
var canvas = document.getElementById("ex1");
var dataUrl = canvas.toDataURL();
Client example: http://tutorials.jenkov.com/html5-canvas/todataurl.html
Server(PHP) example http://html5stars.com/?p=99