当前位置: 首页 > 知识库问答 >
问题:

javascript - Vue / Javascript 解析二进制图像文件错误?

苏彦君
2024-07-12

用 tauri + Vue3 + markdown-it 构建的 markdown 解析工具。其中 template 的内容使用 v-html 绑定,所以解析出的图片是相对路径。

使用 npm run tauri dev 时顺利渲染,但是在 npm run tauri build 后,由于安全设置的问题,前端无法读取图片,此时路径依然显示相对路径 ../img/xxx.png,实际为 https://tauri.localhost/img/xxx.png

按照 convertFileSrc 案例尝试修改 tauri.conf.json,将 tauri.security.csp 设为 "csp": "default-src 'self'; img-src '*' asset: https://asset.localhost",其中 img-src 按照建议修改为 "*",另外还有一些尝试,都无法直接由前端 src 中的绝对路径来显示图片,所以考虑在检测到 md 文件渲染完毕后由 tauri/api/fs 直接读取本地文件或在 Rust 后端中将二进制文件信息传到前端,用 blob 解析。

其中,在 Rust 后端读取文件的方法试过,直到 blob 解析都没有报错,但不能正常显示图片,不知道是不是数据格式问题。而直接由前端调用 fs 读取 也出现了相似的问题,在最后一步无法显示图片。 由于后续测试过程中基本没有用到后端,预估是 Vue 或者图片文件解析的问题。

首先将 tauri.conf.json 中的 tauri.allowlist.fs 设为:

    "fs": {
        "all": true,
        "scope": ["D:/**", "E:/**"]
    }

即允许 fs 读取两个盘中所有文件;

将上面提到的 csp 设为: "csp": "asset:"

前端对图片的处理主要是:

let img_path = "E:/myProjects2/tauri_vue/mdren/img/a-1-01.png";
const contents = await readBinaryFile(img_path);  // contents 为 Uint8Array,须转换为 string
const str_contents = () => {
  let binary = "";
  let len = contents.byteLength;
  for (let i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return binary;
}
let src = window.btoa(str_contents);  // window.btoa 处理字符串格式的二进制图片数据

// ...

// 上面已经将 markdown 渲染到了 html 中,
// 检测到 DOM 变化后调用 reloadImg,将里面的 <img id="img-to-remove" ...> 重新渲染
async function reloadImg() {
  console.log("function called");
  let img_element = document.querySelectorAll("#img-to-remove");
  console.log(img_element);
  img_element.forEach(async (element) => {
    element.src = "data:image/png;base64," + src;
  });
}

在软件中按 F12 调出开发者工具后,可以看到对应图片的 src 是正常的,但是图片不确定是否有编码等错误,表现为损坏或未正常加载的形式。

结果如图


重新做了个小 demo,未用到 Rust 后端,前端代码如下:

components/imgDecode.vue

<script setup>
import { nextTick, ref } from "vue";
import markdownIt from "markdown-it";
import { invoke, convertFileSrc } from '@tauri-apps/api/tauri';
import { resolve, resourceDir } from '@tauri-apps/api/path';
import { readBinaryFile } from "@tauri-apps/api/fs";

const md = markdownIt();
md.set({ html: true });
const md_context = ref();

// 任选一张图片为例
let img_path = "E:/myProjects2/tauri_vue/mdren/img/a-1-01.png";
const contents = await readBinaryFile(img_path);
const str_contents = () => {
  let binary = "";
  let len = contents.byteLength;
  for (let i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return binary;
}
let src = window.btoa(str_contents);

currentLogics();

async function currentLogics() {
  try {
    // 先解析 markdown 文件
    await solveMd();
    // 重新渲染
    nextTick(() => {
      reloadImg();
    })
  } catch (e) {
    console.log(e);
  }
}

async function solveMd() {
  md_context.value = await md.render("$\\xRightarrow{aaaaaaaaaaaaaaaaaaa}$\n\n<img id='img-to-remove' src='../img/a-1-01.png'>");
}

async function reloadImg() {
  console.log("function called");
  let img_element = document.querySelectorAll("#img-to-remove");
  console.log(img_element);
  img_element.forEach(async (element) => {
    element.src = "data:image/png;base64," + src;
  });
}
</script>

<template>
    <div v-html="md_context"></div>
</template>

<style scoped>

</style>

App.vue

<script setup>
import imgDecode from "./components/imgDecode.vue";
</script>

<template>
    <Suspense>
        <resolveData />
    </Suspense>
</template>

<style scoped>

</style>

共有1个答案

岳嘉悦
2024-07-12

解决了,不用 window.btoa,还用 blob 就行:

let img_path = "E:/myProjects2/tauri_vue/mdren/img/a-1-01.png";
const contents = await readBinaryFile(img_path);
let blob = new Blob([contents], { type: "image/png" });

async function reloadImg() {
  console.log("function called");
  let img_element = document.querySelectorAll("#img-to-remove");
  console.log(img_element);
  img_element.forEach(async (element) => {
    element.src = URL.createObjectURL(blob);
  });
}

之前用 blob 不行应该是 csp 忘了改或者 Rust 后端传过来的数据有问题。

在软件里再试一次,希望能过。

 类似资料:
  • 我正在使用Coingecko API。但我就是无法解析数据。下面是示例数据。解析我要做的每个块。 https://api.coingecko.com/api/v3/exchanges 我使用的示例代码: null null

  • 问题内容: 我有一个混合二进制数据和文本数据的文件。我想通过正则表达式解析它,但出现此错误: 我猜该消息意味着Python不想解析二进制文件。我正在打开带有标志的文件。 如何在Python中使用正则表达式解析二进制文件? 编辑: 我正在使用Python 3.2.0 问题答案: 我认为您使用Python 3。 1.以 二进制模式 打开文件很简单但是很微妙。与在文本模式下打开它的唯一区别是mode参数

  • 问题内容: 我会马上追逐。现在,我正在开发基于Web的应用程序。它具有基于PHP REST的体系结构,可提供XML文档。在许多这些文档中,属性是十六进制编码的图片字符串。 在客户端,jQuery AJAX获取其中包含图片的XML文档。我需要在某些标签中显示上述图片。但是,我缺乏有关此类方法的知识,因此在这里寻求帮助。 目标:以十六进制或base64 >>> HTML显示的图像的JavaScript

  • 问题内容: 我有一个JavaScript文件,我想在其中包含一些php代码。问题是我在PHP上也有一些定义,我也想在JS上使用。 有没有办法在HTML中包含.js文件,从而允许服务器首先使用php解释它(在下载到客户端之前)? 谢谢 :) 问题答案: 在输出任何内容之前,您还需要输出正确的标头,您应该具有以下内容: 编辑:正如@Tony_A指出的,应该是。我认为在2010年写这篇文章时,它并不重要

  • objdump工具用来显示二进制文件的信息,就是以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。 14.1. 常用参数说明 -f 显示文件头信息 -D 反汇编所有section (-d反汇编特定section) -h 显示目标文件各个section的头部摘要信息 -x 显示所有可用的头信息,包括符号表、重定位入口。-x 等价于 -a -f -h -r -t 同时指定。 -i 显示对于

  • 问题内容: 有什么方法可以将图像转换为javascript中的二进制数据,反之亦然。 问题答案: 我想用JavaScript获取图像数据?回答您的问题: 将标签传递给此功能。它将以base64编码返回图像。但是它将被重新编码。因此,您无法访问原始图像数据。