Load Image/Video from IndexedDB - javascript

I am working on a PWA project where I have created an IndexedDB and stored the images and videos in it. On the next reload of page, if image/video is available in IndexedDB, it should load it from there.
function fetchMedia(id) {
var transaction = db.transaction(["media"]);
var objectStore = transaction.objectStore("media");
var request = objectStore.get(id);
request.onerror = function(event) {
console.log("Unable to retrieve daa from database!");
return "";
};
request.onsuccess = function(event) {
var imgFile = request.result;
console.log(imgFile)
var imgURL = window.URL.createObjectURL(imgFile);
return imgURL;
};
}
It always returns undefined.
When I console.log the imgFile, it shows that it's there in the IndexedDB:
File in IndexedDB:
I have also tried this but no success yet:
var imgURL = window.URL.createObjectURL(new Blob(imgFile, {'type': 'application/octet-stream'}));
What's the correct approach to load the files from IndexedDB?

If your screenshot is accurate, then request.result is not an image, it's an object {id: '13388-7247-6247-62584', file: Blob, ...}. You didn't just store the image file, you wrapped it in an object. So what you're getting back out is an object.
Try imgFile = request.result.file; instead.

You cannot return inside the callback, you should wrap it in a promise.

Related

IPFS return file url

Im trying to do a file upload function to IPFS that returns the string of the url for where the file is located. But I cannot get it to return it. I have tried using var and window to declare the variable but it always returns undefined.Also defined the enlace outside of the function but still it always declare undefined. Its like its not updating the value outside of the function. As the console log after it does print the url. (and yes I know there is some trash code, I have been trying to debug the problem)
function upload() {
const reader = new FileReader();
reader.onloadend = function() {
const ipfs = window.IpfsApi('localhost', 5001) // Connect to IPFS
const buf = buffer.Buffer(reader.result) // Convert data into buffer
ipfs.files.add(buf, (err, result) => { // Upload buffer to IPFS
if(err) {
console.error(err)
return
}
window.enlace = `http://127.0.0.1:8080/ipfs/${result[0].hash}`
console.log(`Url --> ${enlace}`)
console.log(typeof enlace)
//document.getElementById("url").innerHTML= url
//document.getElementById("url").href= url
//document.getElementById("output").src = url
})
}
const photo = document.getElementById("photo");
reader.readAsArrayBuffer(photo.files[0]); // Read Provided File
return window.enlace;
}
I believe ipfs.add is asynchronous, which means return window.enlace executes before window.enlace is set inside of your callback funcion.

How to save a copy of an image (located at a URL) to Firebase Storage (web) using Javascript?

I'm trying to create a copy of an image (which is located at a url), and save it to Firebase's storage facility. I want to store the actual image file and not just the url. If I understand correctly, I first need to convert the image at the url to a blob or file and then upload the data to the Firebase storage.
This is my current attempt with Javascript:
function savePicture(){
var url = ["http://carltonvet.com.au/sites/default/files/styles/large/public/images/article/cats.jpg"];
var blobpic = new Blob(url, {type: 'file'});
console.log(blobpic);
var user = firebase.auth().currentUser;
if (user != null) {
var userid = user.uid;
var ref = firebase.storage().ref(userid + "profilePhoto");
ref.put(blobpic).then(function(snapshot) {
console.log('Picture is uploaded!');
console.log(snapshot);
var filePath = snapshot.metadata.fullPath;
document.getElementById('picTestAddress').innerHTML = ""+filePath;
document.getElementById('picTestImage').src = ""+filePath;
});
}else{
console.log("Something went wrong, user is null.");
}
}
I have two HTML tags like this:
<div id="picTestAddress"></div>
<img id="picTestImage" />
I'm pretty sure this is only saving the url and not the physical image.
The "picTestAddress" gets filled in with "qAjnfi387DHhd389D9j3r/profilePhoto", and the console shows the following error for "picTestImage": GET file:///android_asset/www/qAjnfi387DHhd389D9j3r/profilePhoto net::ERR_FILE_NOT_FOUND
I'm using Firebase for Web and Cordova. And I'm testing the app on my android phone.
I understand that the error is because it's looking for the image on my phone's local file system. This makes sense to me, so I thought I could fix this by appending my app's address to the beginning of the filePath (eg: document.getElementById('picTestImage').src = "https://firebasestorage.googleapis.com/v0/b/MY_APP.appspot.com/o/"+filePath;).
To find the correct path, I navigated to the file's location in the Firebase console and copied the "Download url" address - but when I checked this (by entering it into my web browser) it loaded a white page which contained one line of text, which was the original url: "http://carltonvet.com.au/sites/default/files/styles/large/public/images/article/cats.jpg"
So now I think I've just saved the url to the storage instead of the actual image file.
I've been following the Firebase docs, and I think I have the uploading part working correctly, but I think I'm failing when it comes to converting the url to the blob/file with Javascript.
I've looked through some other questions, such as this one: How to store and view images on firebase? and was going to follow the example here: https://github.com/firebase/firepano but it says that it's now a legacy example and I can't seem to find an updated version in Firebase's samples section.
Any advice or help with how to do this would be really appreciated.
Thank you in advance!
Looks good, though I'd also consider a promisified version:
function getBlob(url) {
return new Promise(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function(event){
var blob = xhr.response;
resolve(blob);
};
xhr.onerror = reject();
xhr.open('GET', url);
xhr.send();
}
}
function storageURLForPhoto(oldURL, newName) {
getBlob(oldURL)
.then(function(blob) {
var picRef = firebase.storage().ref().child(newName);
return picRef.put(blob)
})
.then(function(snapshot) {
return snapshot.downloadURL;
});
.catch(function() {
// handle any errors
})
}
Little easier to reason about :)
The following works:
function savePhoto(){
var url = "http://www.planetware.com/photos-large/F/france-paris-eiffel-tower.jpg";
// First, download the file:
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function(event) {
var blob = xhr.response;
// Get the current user:
var user = firebase.auth().currentUser;
if (user != null) {
var userid = user.uid;
// Define where to store the picture:
var picRef = firebase.storage().ref(userid + "/profilePhoto");
// Store the picture:
picRef.put(blob).then(function(snapshot) {
console.log('Picture uploaded!');
// Now get image from storage and display in div...
picRef.getDownloadURL().then(function(pic) {
var userspic = pic;
document.getElementById('picTestImage').src = userspic;
}).catch(function(error) {
console.log("There was an error: "+error);
});
});
}else{
console.log("We weren't able to confirm there is a current user, something went wrong.");
}
};
xhr.open('GET', url);
xhr.send();
}

Image in localstorage function doesn't work

I'm wrting a function which takes an image from a file input from a form and enables me to put it in localstorage. The function I wrote to achieve this:
function getImage() {
var pic = document.getElementById("image").files[0];
var imgUrl;
var reader = new FileReader();
reader.onload = function(e) {
var imgURL = reader.result;
saveDataToLocalStorage(imgURL);
return imgUrl;
}
}
Then in another function I call this function and create a JSON entry in which I store values from other form inputs including the image. It looks like this:
var imgUrl = getImage();
// Create new JSON entry
var json_entry = {'title': titleField.val(),
'image': imgUrl,
'content': contentField.val(),
'location': location};
Sadly the value of imgUrl is undefined.. There are no console errors. What am I doing wrong? And how can I fix this?
I honestly don't know much about the FileReader object, but I can see just from glancing at your JS that (at least) one thing is off:
var imgUrl = getImage();
Your getImage function doesn't return anything; so imgUrl is definitely going to be undefined above.
If you want to do something with the result property of your FileReader, then you need to do so w/ a callback since you're handling the (asynchronous) onload event:
function getImage(callback) {
// What are you doing with this?
var pic = document.getElementById("image").files[0];
var reader = new FileReader();
reader.onload = function(e) {
var imgURL = reader.result;
saveDataToLocalStorage(imgURL);
// Note the difference here: rather than return from the event handler
// (which effectively does nothing) we pass the result to a callback.
callback(imgUrl);
}
// I assume you actually need to load something with the FileReader?
}
And then:
getImage(function(imgUrl) {
var json_entry = {
'title': titleField.val(),
'image': imgUrl,
'content': contentField.val(),
'location': location
};
});
It looks like you are forgetting to set the reader to readAsDataUrl. Likely the value is coming back as undefined because localStorage does not inherently know how to serialize binary data. Setting the reader to readAsDataUrl changes reader.result onload.
var reader = new FileReader();
reader.onload = function(e) {
var imgURL = reader.result;
saveDataToLocalStorage(imgURL);
callback(imgUrl);
};
// add this line
reader.readAsDataURL(pic);
Have a look at this article, especially the section titled Reading Files. Note in the linked example the author uses e.target.result instead of reader.result. This should be the same value.

Store retrieved data from indexed DB to a variable

I am using the following code to read data from Indexed DB and save it in variable allDownloadContent
ereaderdownload.indexedDB.getAllTodoItems = function() {
/*var todos = document.getElementById("todoItems");
todos.innerHTML = "";
*/
var db = ereaderdownload.indexedDB.db;
var trans = db.transaction(["downloadcontent"], "readwrite");
var store = trans.objectStore("downloadcontent");
var request = store.get(0);
request.onsuccess = function(e) {
console.log(e.target.result);
};
// Get everything in the store;
var cursorRequest = store.openCursor();
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!!result == false)
return;
allDownloadContent.push(result);
result.continue();
};
alert("content "+allDownloadContent[0]);
cursorRequest.onerror = ereaderdownload.indexedDB.onerror;
};
When I call the getAllTodoItems method from another Javascript file I am getting a alert message content undefined
since the cursorRequest.onsuccess method executes async I am getting undefined.
I cannot make use of web workers since it is not supported in chrome.
I tried promise in Jquery. Still I am getting the same alert message.
Please help me in resolving the issue.
As for now all browsers only support the Indexed-db ASync API, and what you need to do is add an event listener to the transaction oncomplete event. This event will fire when cursor is closed. From there you can return to your code:
trans.oncomplete = function (event) {
console.log('transaction completed');
yourFunction();
};

Is it possible to save a File object in LocalStorage and then reload a File via FileReader when a user comes back to a page?

For example, say the user loads some very large images or media files in to your web app. When they return you want your app to show what they've previously loaded, but can't keep the actual file data in LocalStorage because the data is too large.
This is NOT possible with localStorage. Data stored in localStorage needs to be one of the primitive types that can be serializable. This does not include the File object.
For example, this will not work as you'd expect:
var el = document.createElement('input');
el.type='file';
el.onchange = function(e) {
localStorage.file = JSON.stringify(this.files[0]);
// LATER ON...
var reader = new FileReader();
reader.onload = function(e) {
var result = this.result; // never reaches here.
};
reader.readAsText(JSON.parse(localStorage.f));
};
document.body.appendChild(el);
The solution is to use a more powerful storage option like writing the file contents to the HTML5 Filesystem or stashing it in IndexedDB.
Technically you can if you just need to save small files in localStorage.
Just base64 that ish and since it's a string... it's localStorage-friendly.
I think localStorage has a ~5MB limit. base64 strings are pretty low file size so this is a feasible way to store small images. If you use this lazy man's way, the downside is you'll have to mind the 5MB limit. I think it could def be a solution depending on your needs.
Yes, this is possible. You can insert whatever information about the file you want into LocalStorage, provided you serialize it to one of the primitive types supported. You can also serialize the whole file into LocalStorage and retrieve that later if you want, but there are limitations on the size of the file depending on browser.
The following shows how to achieve this using two different approaches:
(function () {
// localStorage with image
var storageFiles = JSON.parse(localStorage.getItem("storageFiles")) || {},
elephant = document.getElementById("elephant"),
storageFilesDate = storageFiles.date,
date = new Date(),
todaysDate = (date.getMonth() + 1).toString() + date.getDate().toString();
// Compare date and create localStorage if it's not existing/too old
if (typeof storageFilesDate === "undefined" || storageFilesDate < todaysDate) {
// Take action when the image has loaded
elephant.addEventListener("load", function () {
var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");
// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
// Draw image into canvas element
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
// Save image as a data URL
storageFiles.elephant = imgCanvas.toDataURL("image/png");
// Set date for localStorage
storageFiles.date = todaysDate;
// Save as JSON in localStorage
try {
localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
}
catch (e) {
console.log("Storage failed: " + e);
}
}, false);
// Set initial image src
elephant.setAttribute("src", "elephant.png");
}
else {
// Use image from localStorage
elephant.setAttribute("src", storageFiles.elephant);
}
// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
rhino = document.getElementById("rhino");
if (rhinoStorage) {
// Reuse existing Data URL from localStorage
rhino.setAttribute("src", rhinoStorage);
}
else {
// Create XHR, BlobBuilder and FileReader objects
var xhr = new XMLHttpRequest(),
blob,
fileReader = new FileReader();
xhr.open("GET", "rhino.png", true);
// Set the responseType to arraybuffer. "blob" is an option too, rendering BlobBuilder unnecessary, but the support for "blob" is not widespread enough yet
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// Create a blob from the response
blob = new Blob([xhr.response], {type: "image/png"});
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
rhino.setAttribute("src", result);
// Store Data URL in localStorage
try {
localStorage.setItem("rhino", result);
}
catch (e) {
console.log("Storage failed: " + e);
}
};
// Load blob as Data URL
fileReader.readAsDataURL(blob);
}
}, false);
// Send XHR
xhr.send();
}
})();
Source

Categories

Resources