I am creating a chrome extension, that saves image urls from previous webpages. Is there any way for me, to upload the images for the user, to a webpages upload section, such as:
Pages upload section
This is what the input html looks like:
<label>
<form>
<input accept="image/*,image/heif,image/heic"
class="mkhogb32" multiple="" type="file">
</form>
</label>
Here is what I have so far:
// load the image
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = result.products[pointer][3];
// loaded
img.onload = function() {
// convert the image into a data url
var dataUrl = getImageDataUrl(img);
var blob = dataUrlToBlob(dataUrl);
console.log(blob);
var form = document.querySelectorAll('form');
var formData = new FormData(form);
formData.append("file", blob, "image_name.png");
var request = new XMLHttpRequest();
// upload
request.open("POST", "/marketplace/create/item");
request.send(formData);
// chrome.storage.local.get( function(result) {
// })
};
//https://scontent-lga3-2.xx.fbcdn.net/v/t1.6435-9/194808255_1211628689294995_1686587396345915188_n.jpg?_nc_cat=107&ccb=1-3&_nc_sid=0d5531&_nc_ohc=mErP2svwNu0AX8Rb0uO&_nc_ht=scontent-lga3-2.xx&oh=c80e70ed525b3a956c4f5c8c70f58048&oe=60E32CCB
// converts an image into a dataurl
function getImageDataUrl(img) {
// Create an empty canvas element
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// Copy the image contents to the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// NOTE: this will throw a cross-origin security exception
// if not done in an extension and if the image is cross-origin
return canvas.toDataURL("image/png");
}
// converts a dataurl into a blob
function dataUrlToBlob(dataUrl) {
var binary = atob(dataUrl.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 want the images to upload when the user clicks my html injected button on the page. This what I want to happen once my injected html button is clicked:
Send image to webpages server (WORKS FINE)
Here is image showing my image was sent to the pages server: My image uploaded to server
Here is what the image looks like if it were manually added:
Manually uploaded image
Have that image uploaded to facebooks "Add Photos" section. (NO PHOTO IS BEING PREVIEWED ON THE ADD PHOTO SECTION)
Is it possible?
Related
I'm trying to reduce image size at the client side before it is being uploaded to the server. I have the following javascript code to generate a reduced sized image of the selected file for upload.
function handleUpload(){
var canvas = document.getElementById("canvas");
var img = document.createElement("img");
// from an input element
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onload = function() {
img.src = reader.result
createCanvas(canvas, img);//method that creates a reduced sized canvas
}
reader.readAsDataURL(file);
var dataurl = canvas.toDataURL("image/jpg");
}
How can I upload the resized Image file to the server in JSF. I have the following JSF tag which is creating the canvas, but still uploads the original file to the server.
<h:inputFile id="file" value="#{managedBean.uploadedFile}" onchange="handleUpload()"/>
PS:
Mojara 2.2
I have an html canvas that shows a preview of an image when the image is selected in an input. This works in Chrome, but I can't seem to get it to work in Safari. Specifically - in Safari - the onchange="previewFile()" does not seem to call the previewFile function.
<canvas id="canvas" width="0" height="0"></canvas>
<h2>Upload a photo </h2>
<input type="file" onchange="previewFile()"><br>
<script type="text/javascript">
// setup the canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// grab the photo and display in canvas
var photo = new Image();
function previewFile() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
photo.src = reader.result;
canvas.height = photo.height;
canvas.width = photo.width;
ctx.drawImage(photo,0,0);
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
</script>
Your problem is certainly due to the fact that you are not waiting for the image has loaded before you try to draw it on the canvas.
Even wen the source is a dataURI, the loading of the image is asynchronous, so you need to wrap your drawing operations in the image's onload event.
var photo = new Image();
photo.onload = function(){
canvas.height = photo.height;
...
}
...
reader.onload = function(){
// this will eventually trigger the image's onload event
photo.src = this.result;
}
But if all you need is to draw your image on the canvas, don't even use a FileReader, actually, the readAsDataURL() method should trigger a I'm doing something wrong error in your brain. Almost all you can do with a dataURI version of a Blob, you can also do it with the Blob itself, without computing it nor polluting the browser's memory.
For example, to display an image for user input, you can use URL.createObjectURL(blob) method.
// setup the canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// grab the photo and display in canvas
var photo = new Image();
// drawing operations should be in the mage's load event
photo.onload = function() {
// if you don't need to display this image elsewhere
URL.revokeObjectURL(this.src);
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
}
photo.onerror = function(e) {
console.warn('file format not recognised as a supported image');
}
file_input.onchange = function() {
// prefer 'this' over DOM selection
var file = this.files[0];
var url = URL.createObjectURL(file);
photo.src = url;
};
<canvas id="canvas" width="0" height="0"></canvas>
<h2>Upload a photo </h2>
<input type="file" id="file_input">
<br>
And for those who need to send this file to their server, use a FormData to send directly the Blob. If you really need a dataURI version, then convert it server-side.
I am using HTML5 inputs to take a picture from camera using below line,
<input id="cameraInput" type="file" accept="image/*;capture=camera"></input>
and getting used image in blob:, using following javascript,
var mobileCameraImage = function() {
var that = this
;
$("#cameraInput").on("change", that.sendMobileImage);
if (!("url" in window) && ("webkitURL" in window)) {
window.URL = window.webkitURL;
}
});
var sendMobileImage = function( event ) {
var that = this;
if (event.target.files.length == 1 && event.target.files[0].type.indexOf("image/") == 0) {
var capturedImage = URL.createObjectURL(event.target.files[0])
;
alert( capturedImage );
}
});
Here, I am getting proper image url but the problem i am facing is to send this image url to the server, After reading blogs i found i can not send Blob: url to the server due to its local instance. Does anyone can help to save the clicked image on local machine on a folder or any where, or to help how i can send this image url to the server.
Thanks in advance.
You may need to submit your form every time via Ajax or you may upload the image data manually. In order to do that, you may draw the image unto a canvas, then obtain the canvas data.
// create an image to receive the data
var img = $('<img>');
// create a canvas to receive the image URL
var canvas = $('<canvas>');
var ctx = canvas[0].getContext("2d");
$("#cameraInput").on("change", function () {
var capturedImage = URL.createObjectURL(this.files[0]);
img.attr('src', capturedImage);
ctx.drawImage(img);
var imageData = canvas[0].toDataURL("image/png");
// do something with the image data
});
Or use a FileReader
// only need to create this once
var reader = new FileReader();
reader.onload = function () {
var imageData = reader.result;
// do something with the image data
};
$("#cameraInput").on("change", function () {
reader.readAsDataURL(this.files[0]);
});
Then you can upload that data to the server.
I have following Problem.
I´m using a canvas to resize pictures a user uploaded to my webapp.
Then I retrieve the picture from the canvas as a base64 encoded string and try to upload it to the parse server.
Since parse supports base64 I thought it could work.
When i upload the images however, there is no image but instead this message for every image file i upload:
{"_ContentType":"image/jpg","_ApplicationId":"MY APPLICATION
ID","_JavaScriptKey":"MY JAVASCRIPT
KEY","_ClientVersion":"js1.3.5","_InstallationId":"THE INSTALLATION
ID","_SessionToken":"THE SESSION TOKEN OF THE CURRENT USER"}
I can retrieve the files, but what i get is no image.
Here is my code for uploading the pictures:
var fileUploadControl = $("#product_pictureUploadModal")[0];
if (fileUploadControl.files.length > 0) {
//THE USER SUCCESSFULLY SELECTED A FILE
var file = fileUploadControl.files[0];
if(file.type.match(/image.*/)){
//RESIZE THE IMAGE AND RETURN a base64 STRING
var resizedImage = resizeImage(file);
//CREATE A PARSE FILE
var name = "picture.jpg";
var parseFile = new Parse.File(name, {base64: resizedImage}, "image/jpg");
parseFile.save().then(function() {
//IMAGE SUCCESSFULLY UPLOADED
},
function(error){
alert(error.message);
});
}else{
//THE USER DIDNT CHOSE A PICTURE
}
}else{
//THE USER DIDNT SELECT A FILE
}
Here is my code for resizing the pictures:
function resizeImage(file){
var MAX_WIDTH = 400;
var image = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var url = window.URL || window.webkitURL;
var src = url.createObjectURL(file);
image.src = src;
return image.onload = function(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(image.width > MAX_WIDTH){
if(image.width > image.height){
image.height = (image.height%image.width)*400;
}else{
image.height = (image.height/image.width)*400;
}
alert("image height " + image.height);
image.width = 400;
}
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0, image.width, image.height);
url.revokeObjectURL(src);
var fileRezized = encodeURIComponent(canvas.toDataURL("image/jpg"));
return fileRezized;
};
}
What am i missing here?
I hope you guys could help me. I put a lot of work and time in this already and I seem to not get any further than this.
I want to resize the image in the browser because otherwise upload speed might be too slow for some people, as my application will be available for mobile phones as well.
greetins from germany, marvin
When you get no dataURL back from the browser, it's often caused by a cross-domain security violation.
The users image likely does not originate on the same domain as your web page, so when you drawImage the users image to the canvas, you are "tainting" the canvas. This tainting will cause .toDataURL to be disallowed which will in turn cause the DataURL uploaded to your server to be empty.
One workaround
As a workaround, you can "round-trip" the user's image:
upload the users image to your server and save it in the same domain as your web pages.
reload the users browser page along with their image served from your own domain.
Another workaround: FileReader
If your users have modern browsers that support FileReader then you can let your users upload images from their local drives in a security compliant way.
Here's example code using FileReader:
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
var reader=new FileReader();
reader.onload=(function(aImg){
return function(e) {
aImg.onload=function(){
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width=aImg.width;
canvas.height=aImg.height;
ctx.drawImage(aImg,0,0);
document.body.appendChild(document.createElement('br'));
document.body.appendChild(canvas);
var u=canvas.toDataURL();
var textarea=document.createElement('textarea');
textarea.value=u;
document.body.appendChild(textarea);
}
// e.target.result is a dataURL for the image
aImg.src = e.target.result;
};
})(img);
reader.readAsDataURL(file);
} // end for
} // end handleFiles
//
$("#fileElem").change(function(e){ handleFiles(this.files); });
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Example: load images to canvas while satisfying security requirements.</h4>
<input type="file" id="fileElem" multiple accept="image/*">
<br>
There is an error in this line:
var fileRezized = encodeURIComponent(canvas.toDataURL("image/jpg"));
There is no mime-type image/jpg in canvas. This would actually default to image/png instead which I guess could confuse the receiver. Just correct the line to:
var fileRezized = encodeURIComponent(canvas.toDataURL("image/jpeg"));
I don't know parse.com, but also try doing this with this line:
var parseFile = new Parse.File(name, {base64: resizedImage}, "image/jpeg");
// ^^
Test case
var canvas = document.querySelector("canvas"), out = document.querySelector("div");
out.innerHTML = canvas.toDataURL("image/jpg") + "<br><br>"; // PNG
out.innerHTML += canvas.toDataURL("image/jpeg"); // JPEG
<canvas width=1 height=1></canvas><div></div>
When i try to add the image in the URL to a PDF file the image comes completley black.
But when I click the download pdf button again the image gets added to the PDF.Only
when I do it the first time, the image comes as black.
function getBase64Image(url) {
alert(url);
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var img = new Image();
img.src = url;
img.style.height ="181px";
img.style.width ="183px";
//img.crossOrigin ="Anonymous";
context.drawImage(img,0,0);
var dataURL = canvas.toDataURL("image/jpeg");
alert(dataURL);
document.body.appendChild(img);
var doc = new jsPDF('landscape');
doc.addImage(img,'JPEG',0,0,50,50);
doc.save('Saved.pdf');
}
getBase64Image("http://localhost:64931/jspdf/download.png");
What happens when you change your code like this:
A changed JPEG to PNG, that worked for me.
function getBase64Image(url) {
alert(url);
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var img = new Image();
img.src = url;
img.style.height ="181px";
img.style.width ="183px";
//img.crossOrigin ="Anonymous";
context.drawImage(img,0,0);
var dataURL = canvas.toDataURL("image/png");
alert(dataURL);
document.body.appendChild(img);
var doc = new jsPDF('landscape');
doc.addImage(img,'PNG',0,0,50,50);
doc.save('Saved.pdf');
}
getBase64Image("http://localhost:64931/jspdf/download.png");
I was facing the same issue yesterday, and writing this answer incase someone finds it useful
What I was trying to achieve?
I was converting the doc (pdf) into a blob and then opening it in a print dialogue, but the image was black.
var blob = new Blob([doc.output()], { type: "application/pdf" });
This is how I was trying to convert it into a blob.
but this resulted in a black image
Solution
jsPDF allows us to add arguments in the output function.
[](jsPDF output api)
adding type as bloburl works for me, as i was opening a print dialogue using the blob url
let iframe = document.createElement("iframe"); //load content in an iframe to print later
document.body.appendChild(iframe);
//* print dialogue
iframe.style.display = "none";
iframe.src = blobURL;
console.log(blobURL) // same blobURL that was received from jsPDF
iframe.onload = function () {
setTimeout(function () {
iframe.focus();
iframe.contentWindow.print(); // opens a print dialogue box
}, 1);
};