download pictures in the frontend and then create data-urls from blobs
This commit is contained in:
@@ -30,6 +30,8 @@ lazy_static = "1.4"
|
||||
parking_lot = "0.12"
|
||||
dotenv = "0.15.0"
|
||||
dotenv_codegen = "0.15.0"
|
||||
kamadak-exif = "0.5.5"
|
||||
image-meta = "0.1.2"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -5,7 +5,7 @@ function getFilesDataTransferItems(dataTransferItems) {
|
||||
// nothing to do
|
||||
} else if (item.isFile) {
|
||||
item.file(file => {
|
||||
file.filepath = path + "/" + file.name; //save full path
|
||||
file.filepath = path + file.name; //save full path
|
||||
folder.push(file);
|
||||
resolve(file);
|
||||
});
|
||||
@@ -17,7 +17,7 @@ function getFilesDataTransferItems(dataTransferItems) {
|
||||
folder.push({ name: item.name, subfolder: subfolder });
|
||||
for (let entry of entries)
|
||||
entriesPromises.push(
|
||||
traverseFileTreePromise(entry, path + "/" + item.name, subfolder)
|
||||
traverseFileTreePromise(entry, path + "/" + item.name + "/", subfolder)
|
||||
);
|
||||
resolve(Promise.all(entriesPromises));
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use super::BasePage;
|
||||
use crate::gallery::Grid;
|
||||
use crate::hooks::use_user_context;
|
||||
@@ -16,6 +18,10 @@ use yew_hooks::prelude::*;
|
||||
|
||||
use common::OutputPicture;
|
||||
|
||||
pub struct MetaData {
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct PhotosWrapper {
|
||||
photos: Vec<String>,
|
||||
@@ -25,6 +31,17 @@ pub struct PhotosUrlsWrapper {
|
||||
photos: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DetailPhoto {
|
||||
key: String,
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DetailPhotoWrapper {
|
||||
photos: Vec<DetailPhoto>,
|
||||
}
|
||||
|
||||
#[function_component(Home)]
|
||||
pub fn home() -> Html {
|
||||
let user_ctx = use_user_context();
|
||||
@@ -39,7 +56,7 @@ pub fn home() -> Html {
|
||||
use_effect_with_deps(
|
||||
move |_| {
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
let url = "/api/pictures/";
|
||||
let url = "/api/photos/get";
|
||||
let fetched_pictures: Vec<OutputPicture> = Request::get(url)
|
||||
.send()
|
||||
.await
|
||||
@@ -118,7 +135,9 @@ pub fn home() -> Html {
|
||||
console_log!("end", uiae.join("\n"));
|
||||
|
||||
let photos: PhotosUrlsWrapper = Request::post("/api/photos/upload")
|
||||
.json(&PhotosWrapper { photos: uiae })
|
||||
.json(&PhotosWrapper {
|
||||
photos: uiae.clone(),
|
||||
})
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
@@ -128,19 +147,48 @@ pub fn home() -> Html {
|
||||
.unwrap();
|
||||
console_log!("{}", serde_json::to_string(&photos).unwrap());
|
||||
|
||||
let mut metadata: Vec<MetaData> = Vec::new();
|
||||
let mut promises: Vec<Promise> = Vec::new();
|
||||
for (file, (_, url)) in files.iter().zip(photos.photos) {
|
||||
for (file, (key, url)) in files.iter().zip(photos.photos) {
|
||||
console_log!("uploading: ", &file.name(), &url);
|
||||
let promise = read_file(file.clone());
|
||||
if let Ok(content) = wasm_bindgen_futures::JsFuture::from(promise).await {
|
||||
let buffer: ArrayBuffer = content.dyn_into().unwrap();
|
||||
let typed_buffer: js_sys::Uint8Array = js_sys::Uint8Array::new(&buffer);
|
||||
let mut buf = vec![0; typed_buffer.length() as usize];
|
||||
typed_buffer.copy_to(&mut buf[..]);
|
||||
console_log!(
|
||||
serde_json::to_string(&buf.len()).unwrap(),
|
||||
serde_json::to_string(&buf).unwrap()
|
||||
);
|
||||
typed_buffer.copy_to(&mut buf);
|
||||
// console_log!(
|
||||
// serde_json::to_string(&buf.len()).unwrap(),
|
||||
// serde_json::to_string(&buf).unwrap()
|
||||
// );
|
||||
let mut md = MetaData {
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
let meta = image_meta::load_from_buf(&buf).unwrap();
|
||||
console_log!(format!(
|
||||
"dims: {}x{}",
|
||||
meta.dimensions.width, meta.dimensions.height
|
||||
));
|
||||
console_log!(format!("animation: {:?}", meta.is_animation()));
|
||||
console_log!(format!("format: {:?}", meta.format));
|
||||
md.height = meta.dimensions.height;
|
||||
md.width = meta.dimensions.width;
|
||||
|
||||
let exifreader = exif::Reader::new();
|
||||
let mut cursor = Cursor::new(&buf);
|
||||
if let Ok(exif) = exifreader.read_from_container(&mut cursor) {
|
||||
for f in exif.fields() {
|
||||
console_log!(format!(
|
||||
"{} {} {}",
|
||||
f.tag,
|
||||
f.ifd_num,
|
||||
f.display_value().with_unit(&exif)
|
||||
));
|
||||
}
|
||||
}
|
||||
metadata.push(md);
|
||||
|
||||
promises.push(upload(buffer, file.type_(), url.clone()));
|
||||
}
|
||||
}
|
||||
@@ -152,6 +200,25 @@ pub fn home() -> Html {
|
||||
};
|
||||
}
|
||||
|
||||
let photos: DetailPhotoWrapper = Request::post("/api/photos/upload/done")
|
||||
.json(&DetailPhotoWrapper {
|
||||
photos: uiae
|
||||
.iter()
|
||||
.zip(metadata)
|
||||
.map(|(p, md)| DetailPhoto {
|
||||
key: p.clone(),
|
||||
width: md.width,
|
||||
height: md.height,
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
console_log!("all uploaded");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ pub struct GridProps {
|
||||
|
||||
#[function_component(Grid)]
|
||||
pub fn grid(props: &GridProps) -> Html {
|
||||
let target_height = 100;
|
||||
let target_height = 200;
|
||||
let container_width = if props.width == 0 { 0 } else { props.width - 4 };
|
||||
let margin = 2;
|
||||
if container_width == 0 {
|
||||
@@ -54,6 +54,7 @@ pub fn grid(props: &GridProps) -> Html {
|
||||
"display: flex;",
|
||||
"flex-wrap: wrap;",
|
||||
"flex-direction: row;",
|
||||
"min-height: 10vh",
|
||||
)}>
|
||||
{ props.pictures.iter().zip(dimensions).map(|(p, d)|
|
||||
html!{
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use common::OutputPicture;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
use web_sys::{window, Blob, HtmlElement, Request, RequestInit, Response, Url};
|
||||
use weblog::console_log;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Properties, PartialEq)]
|
||||
@@ -19,9 +23,42 @@ pub fn picture(props: &PictureProps) -> Html {
|
||||
let margin = props.margin.to_string();
|
||||
let width = props.width.to_string();
|
||||
let height = props.height.to_string();
|
||||
|
||||
let node = use_node_ref();
|
||||
|
||||
{
|
||||
let node = node.clone();
|
||||
use_effect_with_deps(
|
||||
move |_| {
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
let mut opts = RequestInit::new();
|
||||
opts.method("GET");
|
||||
let request = Request::new_with_str_and_init(&thumb, &opts).unwrap();
|
||||
let window = web_sys::window().unwrap();
|
||||
let resp = JsFuture::from(window.fetch_with_request(&request))
|
||||
.await
|
||||
.unwrap();
|
||||
let resp: Response = resp.dyn_into().unwrap();
|
||||
let blob: Blob = JsFuture::from(resp.blob().unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
.dyn_into()
|
||||
.unwrap();
|
||||
let url = Url::create_object_url_with_blob(&blob).unwrap();
|
||||
|
||||
if let Some(element) = node.cast::<HtmlElement>() {
|
||||
element.set_attribute("src", &url);
|
||||
}
|
||||
});
|
||||
|| ()
|
||||
},
|
||||
(),
|
||||
);
|
||||
}
|
||||
|
||||
html! {
|
||||
<>
|
||||
<img style={format!("margin: {}px; display: block;", margin)} src={thumb} width={width} height={height} />
|
||||
<img ref={node} style={format!("margin: {}px; display: block;", margin)} width={width} height={height} />
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user