derek-zhou

derek-zhou

How do I modify the upload content before the upload?

Liveview’s upload is simple enough to use. However, I now have a need to modify the file content before the upload. Specifically, I want to scale down the image at the client side before sending the potentially very large file over the network. Is there any javascript hook that enable me to do that?

Marked As Solved

derek-zhou

derek-zhou

Yes, I scale the image using client side js and store the result in a blob. Then I chunk the blob, basse64 encode them, and send the chunks in-band in with pushEvent

See here for the js part:

https://github.com/derek-zhou/gara/blob/main/lib/gara_web/components/header.hooks.js

Also Liked

mcrumm

mcrumm

Phoenix Core Team

One option is to use a hidden <.live_file_input /> and then use this.upload() on a client-side hook to enqueue the resized file. Here is a brief example:

In your HEEx template:

<!-- Users select files with this file input. -->
<input type="file" id="resize-target" phx-hook="ResizeInput" data-upload-target="images" />

<form phx-change="change" phx-submit="submit">
  <!-- The live file input is hidden because users will not interact with it directly. -->
  <.live_file_input upload={@uploads.images} style="display:none;" />
  <button type="submit">Upload</button>
</form>

…and the ResizeInput hook:

// assets/js/resize_input.js
import { convertResizeImageFiles } from './image_utils'

// This hook attaches to a custom input element to resize selected images.
export default ResizeInput = {
  getUploadTarget() { return this.el.dataset.uploadTarget },
  mounted() {
    this.el.addEventListener("change", (e) => {
      e.preventDefault()
      e.stopImmediatePropagation()

      if (this.el.files && this.el.files.length > 0) {
        convertResizeImageFiles(this.el.files, 300, (resizedImageBlob) => {
          // Enqueues the resized blob on the <.live_file_input />.
          this.upload(this.getUploadTarget(), [resizedImageBlob])
        })
      }
    })
  }
}

I put the visible file input outside of the live form so that its change events don’t trigger additional messages to the server.

You can find a working demo in my live_upload_example repo: Add client-side resize demo · mcrumm/live_upload_example@5c797aa · GitHub

Hope that helps!

PS– Please forgive my JavaScript. The convertResizeImageFiles callback should really receive a list of files, that way the upload function would only need to be invoked once for each batch of selected files, however I am currently on vacation so this is the best I could do on short notice :smiley:

sreyansjain

sreyansjain

This is very nice and can be used to consume files directly on the server instead of loading to an external storage.
Thank you so much for sharing (while being on vacation, really appreciate it.).
Enjoy your vacation.

polypush135

polypush135

I was just sharing with someone about this yesterday.

In short, yeah everything is done client side via hooks.

In one example I load an image with a wasm lib via a canvas on the dom, that is used to resize.
The other, I upload file to a bucket, call third party scale api with bucket path, download scaled image back to clients re-upload with new signed url.

Edit: I should add its easy to overload the browser in the case of the canvas/wasm workflow.
On a phone loading several 24mb sized images in to canvas has been able to crash a mobile browser really fast and given the size of raw phone images now it was a common issue I seen. The better of the two approaches I found was to use a signed url to throw the image at a buck then trigger a worker to async resize the image and fetch it later and or move it from a temp bucket to a permanent place. Uploading large files to a bucket is a non issue and its was better to have a back up of the source upload in my case too. I also found minio for self hosting buckets which made going the object store approach a lot for effective for me. That said I would love it if there was a really good full client side solution to this. Y

Last Post!

sreyansjain

sreyansjain

This is very nice and can be used to consume files directly on the server instead of loading to an external storage.
Thank you so much for sharing (while being on vacation, really appreciate it.).
Enjoy your vacation.

Where Next?

Popular in Questions Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 130286 1222
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31494 112
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement