Как прочитать файл с JavaScript в WebAssembly с помощью Rust? - PullRequest
0 голосов
/ 26 июня 2018

Как я могу передать File для чтения в контексте памяти WebAssembly?

Легко читать файл в браузере с помощью JavaScript:

<input class="file-selector" type="file" id="files" name="files[]" />

Мне удалось загрузить код WebAssembly, написанный на Rust, с ящиком stdweb , добавить прослушиватель событий в элемент DOM и запустить FileReader:

let reader = FileReader::new();
let file_input_element: InputElement = document().query_selector(".file-selector").unwrap().unwrap().try_into().unwrap();
file_input_element.add_event_listener(enclose!( (reader, file_input_element) move |event: InputEvent| {
    // mystery part
}));

В JavaScript я бы взял файл из элемента и передал его читателю, однако для API stdweb нужна следующая подпись:

pub fn read_as_array_buffer<T: IBlob>(&self, blob: &T) -> Result<(), TODO>

Я понятия не имею, как реализовать IBlob, и я уверен, что мне не хватает чего-то очевидного в API stdweb или в моем понимании WebAssembly / Rust. Я надеялся, что есть что-то менее многословное, чем , конвертирующее материал в UTF-8 .

Ответы [ 2 ]

0 голосов
/ 08 июля 2018

Работает, когда сам FileReader передается из JavaScript в WebAssembly. Это также кажется чистым подходом, потому что данные все равно должны быть прочитаны API JavaScript - нет необходимости вызывать JS из WASM.

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Read to wasm</title>
</head>
<body>
<input type="file" id="file-input"/>
<script src="reader.js"></script>
<script>
    var fileReader = new FileReader();
    fileReader.onloadend = e => Rust.reader
            .then(reader=> {
                window.alert(reader.print_result(fileReader));
            });

    var fileInputElement = document.getElementById("file-input");
    fileInputElement.addEventListener("change", e => fileReader.readAsText(fileInputElement.files[0]));
</script>
</body>
</html>

main.rs

#![feature(proc_macro)]

#[macro_use]
extern crate stdweb;

use stdweb::js_export;
use stdweb::web::FileReader;
use stdweb::web::FileReaderResult;

#[js_export]
fn print_result(file_reader: FileReader) -> String {
    match file_reader.result() {
        Some(value) => match value {
            FileReaderResult::String(value) => value,
            _ => String::from("not a text"),
        }
        None => String::from("empty")
    }
}

fn main() {
    stdweb::initialize();

    stdweb::event_loop();
}
0 голосов
/ 04 июля 2018

Мне удалось получить доступ к объекту файла и передать его на FileReader следующим образом:

let reader = FileReader::new();
let file_input_element: InputElement = document()
    .query_selector(".file-selector")
    .unwrap()
    .unwrap()
    .try_into()
    .unwrap();

file_input_element.add_event_listener(
    enclose!( (reader, file_input_element) move |event: InputEvent| {
        let file = js!{return @{&file_input_element}.files[0]};
        let real_file: stdweb::web::Blob = file.try_into().unwrap();

        reader.read_as_text(&real_file);
    }

Этот код компилируется. Однако данные никогда не становятся доступными через reader.result().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...