如何选择一个文件作为字节或rust wasm中的文本? 我正在尝试获取在按钮单击时触发的文件上载的文件的Vec

问题描述 投票:0回答:2
(或更理想地是blob objecturl)。

我猜这将需要一个不可见的dom在DOM中的某个地方,但我不知道如何利用

<input>
和/或
web_sys
获取内容或blobokbocturl.

A受JS触发的输入可能不会做到这一点,因为许多浏览器不会让您从JS触发文件输入,这是有充分理由的。如果您认为它很难看,则可以使用
gloo
S
掩盖输入。除此之外,您还需要通过
label

rust webassembly gloo web-sys
2个回答
5
投票
的API摆动自己。非常痛苦,那是:

HtmlInputElement

(如果您对代码有疑问,请问。但是要详细解释它太多了。)
额外,您需要的功能
use js_sys::{Object, Reflect, Uint8Array}; use wasm_bindgen::{prelude::*, JsCast}; use wasm_bindgen_futures::JsFuture; use web_sys::*; #[wasm_bindgen(start)] pub fn init() { // Just some setup for the example std::panic::set_hook(Box::new(console_error_panic_hook::hook)); let window = window().unwrap(); let document = window.document().unwrap(); let body = document.body().unwrap(); while let Some(child) = body.first_child() { body.remove_child(&child).unwrap(); } // Create the actual input element let input = document .create_element("input") .expect_throw("Create input") .dyn_into::<HtmlInputElement>() .unwrap(); input .set_attribute("type", "file") .expect_throw("Set input type file"); let recv_file = { let input = input.clone(); Closure::<dyn FnMut()>::wrap(Box::new(move || { let input = input.clone(); wasm_bindgen_futures::spawn_local(async move { file_callback(input.files()).await; }) })) }; input .add_event_listener_with_callback("change", recv_file.as_ref().dyn_ref().unwrap()) .expect_throw("Listen for file upload"); recv_file.forget(); // TODO: this leaks. I forgot how to get around that. body.append_child(&input).unwrap(); } async fn file_callback(files: Option<FileList>) { let files = match files { Some(files) => files, None => return, }; for i in 0..files.length() { let file = match files.item(i) { Some(file) => file, None => continue, }; console::log_2(&"File:".into(), &file.name().into()); let reader = file .stream() .get_reader() .dyn_into::<ReadableStreamDefaultReader>() .expect_throw("Reader is reader"); let mut data = Vec::new(); loop { let chunk = JsFuture::from(reader.read()) .await .expect_throw("Read") .dyn_into::<Object>() .unwrap(); // ReadableStreamReadResult is somehow wrong. So go by hand. Might be a web-sys bug. let done = Reflect::get(&chunk, &"done".into()).expect_throw("Get done"); if done.is_truthy() { break; } let chunk = Reflect::get(&chunk, &"value".into()) .expect_throw("Get chunk") .dyn_into::<Uint8Array>() .expect_throw("bytes are bytes"); let data_len = data.len(); data.resize(data_len + chunk.length() as usize, 255); chunk.copy_to(&mut data[data_len..]); } console::log_2( &"Got data".into(), &String::from_utf8_lossy(&data).into_owned().into(), ); } }
才能起作用:

web-sys

如果您在启用

[dependencies.web-sys] version = "0.3.60" features = ["Window", "Navigator", "console", "Document", "HtmlInputElement", "Event", "EventTarget", "FileList", "File", "Blob", "ReadableStream", "ReadableStreamDefaultReader", "ReadableStreamReadResult"]

功能上使用

gloo
,则可以更整齐地实现第二个功能:

futures

thanks to Caesar I最终以此代码与

async fn file_callback(files: Option<FileList>) {
    let files = gloo::file::FileList::from(files.expect_throw("empty files"));
    for file in files.iter() {
        console_dbg!("File:", file.name());
        let data = gloo::file::futures::read_as_bytes(file)
            .await
            .expect_throw("read file");
        console_dbg!("Got data", String::from_utf8_lossy(&data));
    }
}
一起用作DOM板条。
dominator

我使用bellow代码,也可以上传文件,但是我不知道如何处理数据?

2
投票

pub fn upload_file_input(mimes: &str, mutable: Mutable<Vec<u8>>) -> Dom { input(|i| { i.class("file-input") .prop("type", "file") .prop("accept", mimes) .apply(|el| { let element: HtmlInputElement = el.__internal_element(); let recv_file = { let input = element.clone(); Closure::<dyn FnMut()>::wrap(Box::new(move || { let input = input.clone(); let mutable = mutable.clone(); wasm_bindgen_futures::spawn_local(async move { file_callback(input.files(), mutable.clone()).await; }) })) }; element .add_event_listener_with_callback( "change", recv_file.as_ref().dyn_ref().unwrap(), ) .expect("Listen for file upload"); recv_file.forget(); el }) }) } async fn file_callback(files: Option<FileList>, mutable: Mutable<Vec<u8>>) { let files = match files { Some(files) => files, None => return, }; for i in 0..files.length() { let file = match files.item(i) { Some(file) => file, None => continue, }; // gloo::console::console_dbg!("File:", &file.name()); let reader = file .stream() .get_reader() .dyn_into::<ReadableStreamDefaultReader>() .expect("Reader is reader"); let mut data = Vec::new(); loop { let chunk = JsFuture::from(reader.read()) .await .expect("Read") .dyn_into::<Object>() .unwrap(); // ReadableStreamReadResult is somehow wrong. So go by hand. Might be a web-sys bug. let done = Reflect::get(&chunk, &"done".into()).expect("Get done"); if done.is_truthy() { break; } let chunk = Reflect::get(&chunk, &"value".into()) .expect("Get chunk") .dyn_into::<Uint8Array>() .expect("bytes are bytes"); let data_len = data.len(); data.resize(data_len + chunk.length() as usize, 255); chunk.copy_to(&mut data[data_len..]); } mutable.set(data); // gloo::console::console_dbg!( // "Got data", // &String::from_utf8_lossy(&data).into_owned(), // ); } }

    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.