I’ve done this a few ways. Mostly its all done on the front end via hooks.
here’s some examples.
Front end UI:
<%= if @uploads.image.entries == [] and @post.thumb_image do %>
<img class="w-[300px] mx-auto mb-2" src={@post.thumb_image} />
<div>
<div class="mt-4 relative rounded-2xl shadow-mb ">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<FontAwesome.LiveView.icon name="copy" type="solid" class="text-slate-100 inline h-6 w-6 fill-current ml-2" />
</div>
<input type="" class="bg-neutral-600 text-slate-100 focus:ring-gray-500 focus:border-gray-500 block w-full pl-14 px-6 py-4 sm:text-sm border-gray-300 rounded-lg" value={@post.cover_image} />
</div>
</div>
<% else %>
<%# Phoenix.LiveView.Helpers.upload_errors/1 returns a list of error atoms %>
<%= for err <- upload_errors(@uploads.image) do %>
<p class="alert alert-danger"><%= error_to_string(err) %></p>
<% end %>
<% end %>
<%= for entry <- @uploads.image.entries do %>
<article class="upload-entry">
<figure>
<%= live_img_preview entry, width: 300 %>
This file has been truncated. show original
callback:
case consume_uploaded_entries(socket, :image, fn %{url: url, md_url: md_url, sm_url: sm_url},
_ ->
{:ok, [url, md_url, sm_url]}
end) do
[[url, md_url, sm_url]] ->
image_map = %{"thumb_image" => sm_url, "cover_image" => md_url, "source_image" => url}
JS callbacks.
let Uploaders = {}
Uploaders.S3 = function(entries, onViewError){
entries.forEach(entry => {
let {full_string, medium_string, small_string} = entry.meta
// console.debug(entry.file)
var blob = new Blob([entry.file], {type: entry.file.type});
let xhr = new XMLHttpRequest()
onViewError(() => xhr.abort())
xhr.onload = () => {
if(xhr.status === 200){
console.debug(entry.file)
const imageUrl = `https://morphic-pro.imgix.net/opalnova/${entry.file.name}`;
fetch(imageUrl + "?w=600")
.then(response => response.blob())
.then(imageBlob => {
let md_xhr = new XMLHttpRequest()
This file has been truncated. show original
In the js call back you can see how I get a signed url, send the file to a bucket, re request the same image via imagx to scale the image, then re-upload the new scaled image via a signed url, in short scaling the image via a 3rd party all done from the client side.
Not saying this a good example but its an example.
Here is a older example where I use a wasm lib to scale the image all 100% client side before I send to s3.
again this is done mostly via js and hooks. In this example I even pull out exif data from the image too.
function draw(target) {
var ctx = document.getElementById('canvas').getContext('2d'),
img = new Image(),
f = document.getElementById("file").files[0],
url = window.URL || window.webkitURL,
src = url.createObjectURL(f);
if (target == "snap") {
let reader = new FileReader();
reader.readAsArrayBuffer(f)
reader.onload = function () {
console.log(reader.result);
import('exifreader')
.then(ExifReader => {
let exif = ExifReader.load(reader.result);
document.getElementById("snap-form_exif_string").value = JSON.stringify(exif)
import('json-formatter-js')
This file has been truncated. show original
2 Likes