I used forge viewer api. Viewer.screenshot() to get the image of a component. It returns a blob url as the image. E.g “blob:localhost:3000/afdijhejsbjdjd”. But I need to save this image to my local server, how can I achieve this? Using Nodejs.
How can I change this blob url to a transferable image url?
We can convert the image Blob URL to a based64 encoded string like the below, and then
function getScreenShotImageBase64(viewer, width, height) {
return new Promise((resolve) => {
viewer.getScreenShot(width, height, blobURL => {
let img = new Image();
let tmpCanvas = document.createElement('canvas');
let ctx = tmpCanvas.getContext('2d');
tmpCanvas.width = width;
tmpCanvas.height = height;
img.onload = function() {
// draw viewer image on canvas
ctx.drawImage(img, 0, 0, width, height);
resolve(tmpCanvas.toDataURL('image/png'));
};
img.src = blobURL;
});
});
}
let imageBase64 = await getScreenShotImageBase64(viewer, viewer.container.offsetWidth, viewer.container.offsetHeight);
Here is the preview of the result:
Afterward, send the base64 string to your backend server, and then you can either save the image base64 string to your database,
Or resave the base64 string to file. For example in nodejs.
fs.writeFileSync(path.join(uploadPath, fileName), new Buffer(base64, 'base64'))
ref: How to upload image using Base64 string in NodeJs
I want to convert my s3 image link into a file object using JavaScript.
I've found out how to do this with an image URI but wasn't able to figure out how to convert the image URL into a URI. Once I do this I could convert it into a file object
Heres the image link:
http://s3.us-east-2.amazonaws.com/rentpop/298%2F2014-mclaren-650s-Spyder-Tarocco-Orange-2.jpg
Source for this code
function getDataUri(url, callback) {
var image = new Image();
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
canvas.getContext('2d').drawImage(this, 0, 0);
// Get raw image data
callback(canvas.toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, ''));
// ... or get as Data URI
callback(canvas.toDataURL('image/png'));
};
image.src = url;
}
// Usage
getDataUri('local_location_to_image.extension', function(dataUri) {
// Do whatever you'd like with the Data URI!
});
In Javascript (w/ Angular 2+) I have an app where I am trying to save a dataURl to localstorage once it has been picked by a user. Currently I have tried the following code but on retrieval I get an empty obj {} as the body.
HTML
<input style="display:none;" type="file" (change)="fileEvent($event)" #file>
Angular File Storage and Retrieval Function
fileEvent(ev: any): void {
console.log('Event select file', ev);
let obj: any = ev.target.files[0];
let file: File = {
Key: obj.name,
ContentType: obj.type,
Size: obj.size,
Body: obj
};
localStorage.setItem("myapp", JSON.stringify(file);
}
getFileFromLocalStorage {
console.log(JSON.parse(localStorage.getItem("myapp"));
}
File Retrieval Response below
You can not store image directly to localstorage like this. First you need to convert the image to Base64. Then save the Base64 string in localStorage value.
Below is function to convert Image into Base64:
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,/, "");
}
Now you can save this to your local storage.
Here is the reference answer on SO.
Using firebase 3.0.x, is it possible to save a base64 encoded image to the new Firebase Storage service?
I am using canvas to resize images in the browser prior to uploading them, and output them as a base64 jpeg. I know that the Storage api can accept Blobs, but IE9 support is needed for my current project.
You only need to use the putString function without converting the BASE64 to blob.
firebase.storage().ref('/your/path/here').child('file_name')
.putString(your_base64_image, ‘base64’, {contentType:’image/jpg’});
Make sure to pass the metadata {contentType:’image/jpg’} as the third parameter (optional) to the function putString in order for you to retrieve the data in an image format.
or simply put:
uploadTask = firebase.storage().ref('/your/path/here').child('file_name').putString(image, 'base64', {contentType:'image/jpg'});
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, // or 'state_changed'
function(snapshot) {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case firebase.storage.TaskState.PAUSED: // or 'paused'
console.log('Upload is paused');
break;
case firebase.storage.TaskState.RUNNING: // or 'running'
console.log('Upload is running');
break;
}
}, function(error) {
console.log(error);
}, function() {
// Upload completed successfully, now we can get the download URL
var downloadURL = uploadTask.snapshot.downloadURL;
});
You can then use the downloadURL to save to firebase.database() and/or to put as an src to an <img> tag.
The latest version of the Firebase SDK supports base64 image uploads. Simply use the putString method from Firebase Storage.
https://firebase.google.com/docs/reference/js/firebase.storage
One small caveat is that sometimes you'll have a base64 String with unnecessary whitespace. For example, I've found that the cordova Camera plugin returns base64 with unnecessary whitespace. The Storage SDK will fail to upload this because JavaScript can't perform it's native atob function - something the Firebase JS does under the hood. You'll have to strip the whitespace - see DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript
Yes, it's possible now. You should use Firebase Storage new method called putString. You may read spec here.
So, Firebase spec says that you have now two methods to store Base64 string and Base64url string:
// Base64 formatted string
var message = '5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64').then(function(snapshot) {
console.log('Uploaded a base64 string!');
});
// Base64url formatted string
var message = '5b6p5Y-344GX44G-44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64url').then(function(snapshot) {
console.log('Uploaded a base64url string!');
})
From my experience, using putString(message, 'base64url') constantly returns Error about bad formated Base64 string code: "storage/invalid-format", message: "Firebase Storage: String does not match format 'base64': Invalid character found". The solution is to cut off beginning of string data:image/jpeg;base64, and use first method instead putString(message, 'base64'). Then it works.
If you use canvas.toBlob() you'll get the byte[] that you need to pass into Firebase Storage.
Quick example:
function save() {
var canvas = document.getElementById("canvas");
canvas.toBlob(blob => {
var storage = firebase.app().storage().ref();
var name = id + "/" + (new Date()).getTime() + ".png";
var f = storage.child("drawings/" + name);
var task = f.put(blob);
task.on('state_changed', function(snapshot) {
}, function(error) {
console.error("Unable to save image.");
console.error(error);
}, function() {
var url = task.snapshot.downloadURL;
console.log("Saved to " + url);
var db = firebase.database();
var chats = db.ref().child("chats");
chats.child(id).child("drawingURL").set(url);
});
});
};
Otherwise you'll have to convert the base64 yourself, for example with atob().
Here are two values I use to help with support on .toBlob() it is less performant however, it gets the job done.
This method takes in the base64 string, the content type (IE: image/png) and a callback for when the blob has been constructed using atob()
var b64_to_blob = function(b64_data, content_type, callback) {
content_type = content_type || '';
var slice_size = 512;
var byte_characters = atob(b64_data);
var byte_arrays = [];
for(var offset = 0; offset < byte_characters.length; offset += slice_size) {
var slice = byte_characters.slice(offset, offset + slice_size);
var byte_numbers = new Array(slice.length);
for(var i = 0; i < slice.length; i++) {
byte_numbers[i] = slice.charCodeAt(i);
}
var byte_array = new Uint8Array(byte_numbers);
byte_arrays.push(byte_array);
}
var blob = new Blob(byte_arrays, {type: content_type});
callback(blob);
};
I use this method to get the base64 value of a direct link when necessary, In my case it's to download a users Facebook photo when they register on my application.
var image_link_to_b64 = function(url, content_type, callback) {
var image = new Image();
image.crossOrigin = 'Anonymous';
image.onload = function() {
var canvas = document.createElement('CANVAS');
var context = canvas.getContext('2d');
var data_url;
canvas.height = this.height;
canvas.width = this.width;
context.drawImage(this, 0, 0);
data_url = canvas.toDataURL(content_type);
data_url = data_url.substr(22);
callback(data_url);
canvas = null;
};
image.src = url;
};
Below is how it looks when adding the information to firebase storage
$fileService.image_link_to_b64(facebook_info.photoURL + '?width=512&height=512', 'image/png', function(b64) {
$fileService.b64_to_blob(b64, 'image/png', function(blob) {
$fileService.upload_user_photo(blob, 'image/png', function(url) {
// Firebase storage download url here
}
}
}
Incase you're wondering upload_user_photo simply uploads to firebase storage:
var upload_user_photo = function(data, blob, callback) {
var upload_task = user_photo_reference.child('user_photo').put(data);
upload_task.on('state_changed', function(snapshot) {
}, function(error) {
alert('error: ', error);
}, function() {
callback(upload_task.snapshot.downloadURL);
});
};]
For IE9 see this polyfill: https://github.com/eligrey/Blob.js/blob/master/Blob.js
This solution works for me using the Google Cloud Storage API.
But it should work also with the Firebase one by replacing the file.save with the ref put method.
const file = storage.file(file_path_in_gs)
const contents = new Uint8Array(Buffer.from(base64ImgStr, 'base64'))
file.save(contents,
{
contentType: img_type,
metadata: {
metadata: {
contentType: img_type,
firebaseStorageDownloadTokens: uuid()
}
}
}
, () => { })
With Firebase SDK 9 for web (as of May 2022)
import { getStorage, ref, uploadString } from "firebase/storage";
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
// Data URL string
const message4 = 'data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message4, 'data_url').then((snapshot) => {
console.log('Uploaded a data_url string!');
});
Earlier this day, I have succeed in converting SVG file to JPEG using javascript. The main steps are:
Get SVG image from a url
Add image to HTML5 Canvas
Convert the Canvas to JPEG encoded in base64
I replicate the getImageFromUrl function on jsPDF-master to achieve this.
var getImageFromUrl = function (url, callback) {
var img = new Image,
data, ret = {
data: null,
pending: true
};
img.onError = function () {
throw new Error('Cannot load image: "' + url + '"');
}
img.onload = function () {
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// Grab the image as a jpeg encoded in base64, but only the data
data = canvas.toDataURL('image/jpeg').slice('data:image/jpeg;base64,'.length);
// Convert the data to binary form
data = atob(data)
document.body.removeChild(canvas);
ret['data'] = data;
ret['pending'] = false;
if (typeof callback === 'function') {
callback(data);
}
}
img.src = url;
return ret;
}
From that function, the image to be converted is actually a file. In my case, I don't have a file but only the raw code (text when you open a SVG file with text editor).
My question is:
How do you add raw code of a SVG file into the HTML canvas? Is this process also have .onload event attribute like image object?
Thank you
You can convert a "raw" (inline) SVG to image by converting it to a Blob and then use that as an image source:
function drawInlineSVG(ctx, rawSVG, callback) {
var
/// create Blob of inlined SVG
svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
/// create URL (handle prefixed version)
domURL = self.URL || self.webkitURL || self,
url = domURL.createObjectURL(svg),
/// create Image
img = new Image;
/// handle image loading
img.onload = function () {
/// draw SVG to canvas
ctx.drawImage(this, 0, 0);
domURL.revokeObjectURL(url);
callback(this);
};
img.src = url;
}
Then call it like this:
var rawSVG = '<svg ... >';
drawInlineSVG(ctx, rawSVG, function(img) {
console.log('done!');
});
An error handler should of course be included for production code (not shown here).
Important to note: You cannot draw inline SVG's if they contain external references (CSS styles, images and so on). This is due to browser's security policies. You would have to convert all external references to inline data (ie. images to data-uris and so on).