Image scraping and sending to the server - javascript

I scraping some pages (I know, I know, I shouldn't, but the info from our intranet is not available in any other reliable way). So I inject a small $(...).each(... $.ajax({})); JavaScript and this works fine.
I got most info out of it, but now I need the images. I can get the URL, but I need to store them on the server (or on my local machine first). I can't use the URL because the images are behind username/password authentication.
Can I send them with a $.ajax(multipart/form post - new FormData()) construct?
All idea's welcome.

One idea is to encode them as base64 strings and store them that way. Here's a fiddle demonstrating the method: http://jsfiddle.net/c8n9d4ce/
I also found this fiddle that likewise demonstrates this method.
My code from the fiddle:
var canvas = document.getElementById("myCanvas");
var srcImg = document.getElementById("sourceImage");
var final = document.getElementById("base64Image");
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
canvas.height = this.height;
canvas.width = this.width;
canvas.getContext('2d').drawImage(this,0,0);
var dataURL = canvas.toDataURL();
canvas = null;
final.src = dataURL;
};
img.src = srcImg.src;
img {
max-width: 100%;
}
<h1>Original Image</h1>
<img src="https://i.imgur.com/5YJ3HQ9.jpg" id="sourceImage">
<h1>Canvas Rendered Image</h1>
<canvas id="myCanvas"></canvas>
<h1>Base64 Encoded Image</h1>
<img id="base64Image">

Seems the way to go, I tried, but got this error: "Cross-origin image load denied by Cross-Origin Resource Sharing policy". I tried the snippet on this webpage (just copy/paste into the console).
function getDataURL(srcImg, done) {
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('canvas');
canvas.height = this.height;
canvas.width = this.width;
canvas.getContext('2d').drawImage(this,0,0);
done(canvas.toDataURL());
};
img.src = srcImg.src;
}
getDataURL($("img")[0], function(data) {
console.log(data);
});

Related

FileReader dragging image from browser window

I have a div where users can drag and drop an image and then, using FileReader, I get the base64 of the image. Works fine.
dropper.ondrop = function (e) {
e.preventDefault();
var file = e.dataTransfer.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
};
My issue is if I have a browser window open and drag and drop an image from the browser I get the error:
Failed to execute 'readAsDataURL' on 'FileReader':
parameter 1 is not of type 'Blob'.
Now, is there any turnaround to get the base64 of an image dragged from the browser window?
Ultimately, is there is a way to get the image URL and then the actual base64 with a server side curl request?
Any idea?
You can use e.dataTransfer.getData('url') to tell whether there's a URL available. Like this:
var url = e.dataTransfer.getData('url');
if(url){
console.log('Url');
console.log(url);
}else{
console.log('File');
var file = e.dataTransfer.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
}
Then, having the URL, you can load an img element and use draw it on a canvas to grab the base64 representation. Like this:
var img = document.createElement('img');
img.crossOrigin = 'anonymous';
img.onload = function(){
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
console.log(canvas.toDataURL());
};
img.src = url;
This would be the "final" product:
var dropper = document.querySelector('div');
dropper.ondragover = function(e) {
e.preventDefault();
}
dropper.ondrop = function (e) {
e.preventDefault();
var url = e.dataTransfer.getData('url');
if(url){
console.log('Url');
console.log(url);
var img = document.createElement('img');
img.crossOrigin = 'anonymous';
img.onload = function(){
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
console.log(canvas.toDataURL());
};
img.src = url;
}else{
console.log('File');
var file = e.dataTransfer.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
}
};
div{
border:1px solid red;
height:240px;
width:100%;
}
<div>Drop here</div>
Also available here: https://jsfiddle.net/8u6Lprrb/1/
The first parameter comes through with the "http://" or "https://" protocol instead of the expected "file://" protocol. and thats why you cant read it with the HTML5 FILE API, so you may want to download and save the file first before trying to read the contents.
on the other hand, you can update an img tag's src attribute with the retrieved url and skip the readDataAsUrl() portion to hotlink the image.

Saving an image for offline use in a Chrome App

I have an image that is being shown in a Chrome App and is from a remote site. I want to be able to save the image locally in case network connection is unavailable.
I've been researching and found some APIs that might help me such as chrome.fileSystem, however, there aren't any simple examples like this.
Would someone be able to provide me with a simple example on how to do this?
It is preferred if the user doesn't have to press save or anything, having the downloading happen in the background. The image changes at random so I need this to be automated if possible.
what about storing it in localStorage?
var image = document.getElementById('bannerImg');
imgData = getBase64Image(image);
localStorage.setItem("imgData", imgData);
then to restore (adapted from this answer):
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;

Javascript: SecurityError with Canvas and Centext2D [duplicate]

I'm loading an image in js and draw it into a canvas. After drawing, i retrieve imageData from the canvas:
var img = new Image();
img.onload = function() {
canvas.drawImage(img, 0, 0);
originalImageData = canvas.getImageData(0,0,width, height)); //chrome fails
}
img.src = 'picture.jpeg';
This works perfectly both in Safari and Firefox, but fails in Chrome with the following message:
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
The javascript file and the image are located in the same directory, so i don't understand the behavior of chorme.
To enable CORS (Cross-Origin Resource Sharing) for your images pass the HTTP header with the image response:
Access-Control-Allow-Origin: *
The origin is determined by domain and protocol (e.g. http and https are not the same) of the webpage and not the location of the script.
If you are running locally using file:// this is generally always seen as a cross domain issue; so its better to go via
http://localhost/
To solve the cross domain issue with file://, you can start chrome with the parameter
--allow-file-access-from-files
var img = new Image();
img.onload = function() {
canvas.drawImage(img, 0, 0);
originalImageData = canvas.getImageData(0,0,width, height)); //chrome will not fail
}
img.crossOrigin = 'http://profile.ak.fbcdn.net/crossdomain.xml';//crossdomain xml file, this is facebook example
img.src = 'picture.jpeg';
Hope this helps
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
originalImageData = ctx.canvas.toDataURL();
}
img.src = 'picture.jpeg';
hope this helps.
If the server response headers contains Access-Control-Allow-Origin: *, then you can fix it from client side: Add an attribute to the image or video.
<img src="..." crossorigin="Anonymous" />
<video src="..." crossorigin="Anonymous"></video>
Otherwise you have to use server side proxy.

Fetching image from url with javascript

I am trying to show an image on my page from a different url.
<body>
<div id="container">
<br />
<canvas width="500px" height="375px" id="canvas">
</canvas>
<img src="http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png" />
</div>
<script>
var img = new Image;
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png";
var timer = setInterval(function () { MyTimer() }, 200);
function MyTimer() {
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0,500,675);
img = new Image;
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png";
}
</script>
The image on the other site is being saved every 1.5 seconds.
The result is that I cant view the image.
Any ideas why?
Thanks!
1. Cache issue
Your MyPicture.png returns Cache-Control: max-age=31536000 in HTTP response. So browser may get image from its cache on second time. You need to add query string something like thie:
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png?time=" + (new Date()).getTime();
2. Too short fetching period.
I think fetching period 200msec is too short. It's better to bind onload event handler to the image object. See How to fetch a remote image to display in a canvas?.
function copyCanvas(img) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
}
function loadImage() {
var img = new Image();
img.onload = function () {
copyCanvas(img);
};
img.src = "http://yinoneliraz-001-site1.smarterasp.net/MyPicture.png?time=" + (new Date()).getTime();
}
3. Double buffering
I think your script intend to pre-load image. So it's better to make a double buffering.
Single Buffering version: http://jsfiddle.net/tokkonoPapa/dSJmy/1/
Double Buffering version: http://jsfiddle.net/tokkonoPapa/dSJmy/2/
You have not defined canvas. Define it first with:
var canvas = document.getElementById('canvas');
Then, use load event to draw image on to the canvas.
Checkout the fiddle, LoadImgURL which demonstrates the whole process.

How to upload image into HTML5 canvas

I am currently using http://paperjs.org to create an HTML5 canvas drawing app. I want to let users upload images into the canvas. I know I need to make a login and signup but is there an easier way? I have seen the HTML5 drag and drop upload.
I assume you mean, to load an image into the canvas and not uploading the image from the canvas.
It'd probably be a good idea to read through all the canvas articles they have over here
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images
But basically what you want to do is create an image in javascript, and set the image.src = to whatever the file location is. In the case of loading images from the user on their end, you're going to want to use the File System API.
Threw together a brief example here: http://jsfiddle.net/influenztial/qy7h5/
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0);
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
One doesn't need a FileReader*, it is better to use the URL.createObjectURL method, which will create a symlink directly to the File on disk. This will incur less memory usage, and will have the added benefit to have only one async event to wait for (the one of the img.onload).
document.getElementById('inp').onchange = function(e) {
var img = new Image();
img.onload = draw;
img.onerror = failed;
img.src = URL.createObjectURL(this.files[0]);
};
function draw() {
var canvas = document.getElementById('canvas');
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0,0);
}
function failed() {
console.error("The provided file couldn't be loaded as an Image media");
}
<input type="file" id="inp">
<canvas id="canvas"></canvas>
*IIRC only a few versions of Chrome did support FileReader while not yet supporting URL.createObejctURL, so if you target these very versions, you might need FileReader..
Modified answer by #kaiido to create a new canvas element each time and append it to a wrapper. Useful when you don't know how many canvases you may need.
Note: There is no new Canvas() constructor, therefore we must use createElement().
document.getElementById('inp').onchange = function(e) {
let img = new Image();
img.onload = draw;
img.onerror = failed;
img.src = URL.createObjectURL(this.files[0]);
};
function draw() {
let canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0, 0);
document.getElementById('gallery').append(canvas);
}
function failed() {
console.error("The provided file couldn't be loaded as an Image media");
}
/* entirely decorative */
#gallery {
display: flex;
gap: 1em;
margin: 1em;
}
#gallery canvas {
height: 100px;
border-radius: .5em;
aspect-ratio: 1/1;
object-fit: cover;
}
<input type="file" id="inp">
<div id='gallery'></div>
The most optimal way of creating an image consumable by the canvas is to create an ImageBitmap out of the File you get from the input.
This will use an optimized path to produce just what the browser needs to render that image, and will store the bitmap data in the GPU, allowing for fast drawing when asked to.
Given this is a quite recent feature (Safari added support only last year), you may want to use a polyfill like this one of mine.
document.querySelector("input").oninput = async (evt) => {
try {
const file = evt.target.files[0];
const bitmap = await createImageBitmap(file);
const canvas = document.querySelector("canvas");
canvas.width = bitmap.width;
canvas.height = bitmap.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(bitmap, 0, 0);
}
catch(err) {
console.error(err);
}
};
<!-- createImageBitmap polyfill for old browsers --> <script src="https://cdn.jsdelivr.net/gh/Kaiido/createImageBitmap/dist/createImageBitmap.js"></script>
<input type="file">
<canvas></canvas>
<script>
window.onload = function() {
var canvas=document.getElementById(“drawing”); // grabs the canvas element
var context=canvas.getContext(“2d”); // returns the 2d context object
var img=new Image() //creates a variable for a new image
img.src= “images/vft.jpg” // specifies the location of the image
context.drawImage(img,20,20); // draws the image at the specified x and y location
}
</script>
Check Demo

Categories