You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tauri+Vue3中使用window.btoa解码二进制图片文件异常

问题:Tauri+Vue3+markdown-it打包后图片无法显示

我用Tauri+Vue3+markdown-it开发了一款Markdown渲染工具,通过v-html绑定内容,图片采用相对路径引用。开发环境执行npm run tauri dev时图片能正常渲染,但打包构建(npm run tauri build)后,因安全策略限制图片无法显示。

已尝试的解决方案

  • 按ConvertFileSrc文档修改tauri.conf.json的tauri.security.csp配置为:

    "default-src 'self'; img-src '*' asset: https://asset.localhost"
    

    图片仍无法显示。

  • 尝试通过Rust后端读取文件并传递至前端,用Blob创建URL,图片显示损坏(开发者工具中src看似正常)。

  • 改用@tauri-apps/api/fs的readBinaryFile接口:

    1. 配置tauri.allowlist.fs:
      "fs": {
          "all": true,
          "scope": ["D:/**", "E:/**"]
      }
      
    2. 将CSP设置为"asset:"
    3. 核心处理逻辑:
      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);
      

    DOM更新后调用reloadImg函数替换img元素的src为"data:image/png;base64," + src,src看似正确,但图片仍显示损坏。我怀疑问题出在readBinaryFile或Rust后端读取文件的环节,CSP与渲染逻辑已验证无问题。

Demo代码

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();

// 项目/img目录中的任意图片
let img_path = "E:/myProjects2/tauri_vue/mdren/img/a-1-01.png";
// 将图片文件从Uint8Array转为字符串,再用window.btoa处理
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();
    // DOM变更后重新渲染图片
    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'>");
  // 忽略\xRightarrow行,markdown-it-katex无法正常拉伸,已用其他方法临时修复
}

async function reloadImg() {
  console.log("函数已调用");
  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>
        <imgDecode />
    </Suspense>
</template>

<style scoped>

</style>

内容的提问来源于stack exchange,提问作者TsurumiTei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 05:27:02