0

我有以下代码:

let bytes: Vec<u8> = load_file_as_bytes("mydoc.docx"); // This gets a byte vec representation of the file mydoc.docx
let uint8arr =  unsafe { js_sys::Uint8Array::view(&bytes) };
let js_value = wasm_bindgen::JsValue::from(uint8arr);
let blob = Blob::new_with_u8_array_sequence_and_options(
    &js_value,
    web_sys::BlobPropertyBag::new().type_("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
).unwrap();
let download_url = web_sys::Url::create_object_url_with_blob(&blob).unwrap();

当我点击链接时,下载的文件是写在 Word 文档中的一堆字节。
这些字节旨在表示 word 文档本身,而不是作为纯文本写入它。
这被编译为 wasm 并在浏览器中运行。
如果我将字节表示为 b64 编码文本并创建一个<a>带有字符串 href 的元素,我会得到正确的表示

let base64_string = base64::encode(&file.bytes);
let download_url = format!("data:{};base64,{}",file.mime_type,base64_string);
// ... set href = &download_url inside dom

但这对于超过几 KB 的文件来说非常慢,并且随着更多文件的添加而变得更慢。
什么是正确的 Rust-> JS 转换以使用create_object_url_with_blob()它以使其按预期运行?

4

1 回答 1

0

看起来这样做的正确方法是将您推Uint8Arrayjs_sys::Array第一个,并且因为js_sys::Array实现了JsCast您可以直接在 blob 中使用它。

我假设这来自内部 JavaScript 类型的某种内部表示js_sys,并且问题中代码的行为可能默认将字节数组视为文本。

工作代码:

let uint8arr = js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(&bytes) }.into()); 
let array = js_sys::Array::new();
array.push(&uint8arr.buffer());
let blob = Blob::new_with_u8_array_sequence_and_options(
&array,
web_sys::BlobPropertyBag::new().type_("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
).unwrap();
let download_url = web_sys::Url::create_object_url_with_blob(&blob).unwrap();

这导致字节实际上被用作 Word 文档,而不是写入空的 Word 文档。

于 2021-10-13T13:47:51.933 回答