How does LiveView image blob preview works?

Hello,

Does anyone knows how the blob:// url that is used in the image preview component is generated when you are uploading a LiveView image?

I’m not sure if that is like an API available from the browser to have a url for an image/file that is being upload at that time so you can access it (to add to <img> tags, for example) without needing to really upload it to the server first and then serve the image from there or something else.

But, if that is the case, can I somehow have access to that blob url before consuming the image/file and use it afterwards?

Basically what I want to do is to allow the user to upload a bunch of images that will be auto-uploaded, meaning that I will consume then as soon as they arrive, the idea is that after I consume it, I will store the file in some place or in memory until the user submits the form.

After an image is consumed, I want to show it in another component so the images can be reordered before I submit it. But the issue is that I don’t have the blob:// url anymore, so I can’t get the image preview. The only solution that I was able to do is to actually use the image url from the consumed file inside the backend, but that is not a good user experience since the browser will have to redownload the same image back from the backend.

It’s created using JavaScript.

The blob url is referencing the image stored in the browser memory.

You can use phx-hook to run JS and get the blob urls

I was looking at the hook LiveImgPreview that will generate that url (actually it will call LiveUploader which will generate the url). But this hook will call URL.revokeObjectURL when it is destroyed, meaning that even if I get the url from a hook, it will still be invalidated by the original live_img_preview component when I remove it.

Also, seems like LiveUploader is not exported, so I can’t just simply import it and create a “fork” of the LiveImgPreview hook that will invoke URL.revokeObjectURL.

you can duplicate logic of LiveImgPreview hook and use LiveUploader

import LiveUploader from "phoenix_live_view/assets/js/phoenix_live_view/live_uploader"

/// ...

this.img = this.el.querySelector("img")
this.ref = this.el.getAttribute("entry-ref")
this.uploadRef = this.el.getAttribute("upload-ref")
this.inputEl = document.getElementById(this.uploadRef)
    
LiveUploader.getEntryDataURL(this.inputEl, this.ref, url => {
  this.img.src = url
})

your component.heex

<div id="ID" entry-ref={@assigns.entry.ref} upload-ref={@assigns.entry.upload_ref} phx-hook="YourOwnHook" >
  <img />
</div>