Reputation: 79
I am making a website, and I'd like to store a picture in a cookie in my account page. When I upload a profile picture, it works fine, but when I reload, the profile picture is the default picture instead of the picture I picked earlier. How do I make it so when I refresh the page the profile picture stays the same instead of being the default picture? My code:
function preview_image(event) {
var reader = new FileReader();
reader.onload = function(){
var output = document.getElementById('output_image');
output.src = reader.result;
}
reader.readAsDataURL(event.target.files[0]);
}
<!DOCTYPE html>
<html>
<body>
<img src="guest.png" id="output_image">
<input type="file"accept="image/*"onchange="preview_image(event)" id="file">
</body>
</html>
EDIT: you can now use php.
Upvotes: 2
Views: 1033
Reputation: 37825
Cookie are not a good place to store a image due to size limitation (it will also send that cookie on every other page to the server and wasting data)
LocalStorage is no good either as it requires to convert the binary into base64 and waste space and time converting to/from base64. LocalStorage is just a simple key/value storage (as strings) and isn't meant to store large data or binary. Everything in localStorage has to be loaded into the memory on every page load so it slows down performances. Only keep small things like theme: "dark-mode"
IndexedDB is a viable option, but all that code that's needed for storing a simple blob (File) isn't worth the complexity of setting up a database/table and working with callbacks
Blinks old sandboxed file system is also grate but it's outdated and not implemented in all browsers
The newer (spec'ed) sandboxed file system access is better! but it's too new and experimental at this point and also only implemented by Blink behind a flag
There is a other place to store raw binary data doe: in cache storage!
<input type=file id=$fileInput>
<img id="$imgElm">
// load image from cache on page load
caches.open('fs').then(cache => {
cache.match('/preview_image')
.then(res => res.blob())
.then(blob => $imgElm.src = URL.createObjectURL(blob))
.catch(() => { /* no img stored */})
})
$fileInput.onchange = async evt => {
// preview the new image
$imgElm.src = URL.createObjectURL($fileInput.files[0])
// cache it
const cache = await caches.open('fs')
await cache.delete('/preview_image') // perhaps not needed
await cache.put('/preview_image', new Response($fileInput.files[0]))
}
Didn't use SO editors since it have disabled storage in sandboxed iframes... here is a fiddle instead: https://jsfiddle.net/2tnwku63/
(select a image, reload the page - and it's still there)
cache was not intended to store files, only request <-> response with service worker in mind, but if you convert files into a response and abuse it a bit in some ways then it can serve as a flat, low level, sandboxed, file system - doe you need to keep track what you store more manually. There is no concept of subfolders in the cache storage... on the + side you can write large data as a ReadableStream
If you want to be more creative then you could always store a hole FormData by doing
const formData = new FormData()
formData.set('image_upload', file)
cache.put(req, new Response(formData))`
Then you can use response.formData().then(fd => fd.get('image_upload'))
to get an actual file back with the FileName included as a File instances (instead of a blob), you could always store the the hole form by just doing new Response(new FormData(formElm))
and you will then have saved all input fields if you have to go back a page and refill every form input
Upvotes: 4
Reputation: 67
You need a storage to do that. Because you are not "saving" the image anywhere, just using it one time. If its just a "test" you can save this image as a Blob using localStorage. And then you should get it from localStorage when page loads.
Check this: Mozilla Window.localStorage
Upvotes: 3