`web_sys::Url::create_object_url_with_blob(&blob)` 未正确格式化二进制数据
Posted
技术标签:
【中文标题】`web_sys::Url::create_object_url_with_blob(&blob)` 未正确格式化二进制数据【英文标题】:`web_sys::Url::create_object_url_with_blob(&blob)` not formatting binary data correctly 【发布时间】:2021-12-02 00:10:58 【问题描述】:我有以下代码:
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 编码文本并制作一个带有字符串 href 的 <a>
元素,我会得到正确的表示形式
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()
以使其按预期运行?
【问题讨论】:
【参考方案1】:看起来正确的方法是先将您的Uint8Array
推送到js_sys::Array
,
因为js_sys::Array
实现了JsCast
,所以您可以直接在blob 中使用它。
我假设这来自 js_sys
中 javascript 类型的某种内部表示,并且问题中代码的行为可能默认将字节数组视为文本。
工作代码:
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 文档。
【讨论】:
没有“js_sys
中的 javascript 类型的内部表示”之类的东西。 js_sys
只是实际 JavaScript API 的类型和绑定。所以这实际上不是 rust 或 WASM 特有的问题,但似乎是 JavaScript Blob
API 本身。以上是关于`web_sys::Url::create_object_url_with_blob(&blob)` 未正确格式化二进制数据的主要内容,如果未能解决你的问题,请参考以下文章