从 unicode 字符串创建数据 URI

问题描述 投票:0回答:4

我正在尝试让 JavaScript 将 unicode 字符串下载为文本文件。我现在需要将 unicode 字符串转换为数据 URL,以便用户可以打开 URL 并下载文件。 这是我的代码的简化:

var myString = "⌀怴ꁴ㥍䯖챻巏ܛ肜怄셀겗孉贜짥孍ಽ펾曍㩜䝺捄칡⡴얳锭劽嫍ᯕ�";

var link = document.createElement('a');
link.setAttribute('href', 'data:text/plain;base64,' + myString);

我不知道要使用什么字符集或如何对我的字符串进行编码 - 我尝试过

encodeURI()
btoa()
的组合,但没有成功。对于某些字符(例如
encodeURI()
),
Uncaught URI Error: malformed URI
给我错误
U+da7b

我希望最终下载的文件具有与初始字符串相同的字符。

javascript unicode data-uri
4个回答
2
投票

data:
URL中使用文本时,不需要使用base64,只需对文本进行百分比编码就足够了,例如:

var link = document.createElement('a');
link.setAttribute('href', 'data:text/plain;charset=UTF-8,' + encodeURIComponent(myString));

encodeURIComponent()
字符集将文本编码为 UTF-8,然后对 UTF-8 字节进行 url 编码,因此在
charset=UTF-8
URL 中包含
data:

但是,如果您仍然想使用 Base64,则不需要对文本进行 url 编码。只需将文本字符集编码为字节,然后对字节进行 Base64 编码,并指定

data:
URL 中使用的字符集,例如:

var link = document.createElement('a');
link.setAttribute('href', 'data:text/plain;charset=UTF-8;base64,' + btoa(unescape(encodeURIComponent(myString))));

0
投票

这对我有用

decodeURIComponent(atob(btoa(encodeURIComponent("中文"))))
// Output: 中文

对于您的案例

\uDA7B
,它失败了,因为它是高代理之一(D800-DBFF),仅当用作代理对的一部分时才有意义。

这就是为什么你这样做时会出现 URIError

encodeURIComponent('\uDA7B') // ERROR

将其与低代理(DC00-DFFF)中的角色配对,它就可以工作:

encodeURIComponent('\uDA7B\uDC01')


0
投票

您可以尝试设置下载属性并使用 URL 编码与 text/plain

const myString = '⌀怴ꁴ㥍䯖챻巏ܛ肜怄셀겗孉贜짥孍ಽ펾曍㩜䝺捄칡⡴얳锭劽嫍ᯕ�';

const link = document.createElement('a');
link.setAttribute('download', 'filename');
link.append("Download!");
link.setAttribute('href', 'data:,' + encodeURI(myString));

document.body.appendChild(link);

0
投票

这个问题在 MDN 上的 Base 64 文档中被称为“Unicode 问题”https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem,建议的解决方案是:

function base64ToBytes(base64) {
  const binString = atob(base64);
  return Uint8Array.from(binString, (m) => m.codePointAt(0));
}

function bytesToBase64(bytes) {
  const binString = String.fromCodePoint(...bytes);
  return btoa(binString);
}

// encoded will be "YSDEgCDwkICAIOaWhyDwn6aE"
const encoded = bytesToBase64(new TextEncoder().encode("a Ā 𐀀 文 🦄"));

// decoded will be "a Ā 𐀀 文 🦄"
const decoded = new TextDecoder().decode(base64ToBytes("YSDEgCDwkICAIOaWhyDwn6aE"));

与涉及

encodeURIComponent
的解决方案不同,当 data-url 用于不应用 URI 解码的内容(例如
<script>
src 属性)时,该解决方案不起作用,此方法适用于所有情况:

const unicorn = `🦄`;
const customScript = `console.log(unicorn);`

function base64(str) {
  const bytes = new TextEncoder().encode(str);
  const binString = String.fromCodePoint(...bytes);
  return btoa(binString);
}

import(`data:text/javascript;base64,${base64(customScript)}`);

© www.soinside.com 2019 - 2024. All rights reserved.