我需要处理本地文件与网页浏览器中的Java脚本.这个过程很繁琐,包括很多RegEx.exec()个,需要一些时间才能完成,所以我把FileReader()和处理程序都放在Web Worker中.最终产品在Google ChromeMicrosoft Edge上运行良好,但在macOS Safari上有问题.

在MacOS Safari 16.5.1中,当通过file:///path/to/localfile.html直接从本地文件系统加载HTML文件时,此(简化的)Java代码无法工作:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script id="worker" type="javascript/worker">
    self.onmessage = function(evt) {
        var file = evt.data;
        var filereader = new FileReaderSync();
        console.log(filereader.readAsText(file,'UTF-8'));
    };
</script>
<script type="text/javascript">
    function on_change(evt) {
        const workerblob = new Blob(
            [document.querySelector('#worker').textContent],
            {type:"text/javascript"});
        new Worker(window.URL.createObjectURL(workerblob)).postMessage(evt.target.files[0]);
    };
</script>
</head>
<body>
<input id="fileselector" type="file" onchange="on_change(event)">
</body>
</html>

Safari Java脚本控制台显示3条错误消息:

  • 无法加载blob:null/ff4c37bb-8ddb-4082-a492-425423e35ef9.
  • 无法加载资源:Cross origin requests are not allowed when using same-origin fetch mode.
  • NotReadableError:I/O读取操作失败.

所以这是某种CORS问题,但我不知道告诉浏览器"允许来源",因为要加载的资源是本地文件.

这附近有什么工作吗?

更多详细信息:

  1. 如果HTML由HTTP服务器托管并通过常规的HTTP/HTTPS请求加载,则它会按预期工作.
  2. Chrome和Edge都不会抱怨CORS问题,因为HTML文件是从本地文件系统加载的.
  3. Safari只会在Web Worker中调用FileReader()时才会抱怨CORS问题.

因为客户不想要另一台Web服务器,所以我应该把这个HTML文件作为最终产品交付.因此,我需要它在从本地文件系统加载时才能工作.

Yes I've tried 100 and get the same result. In fact I'm using 100 in my final product and just want to simplify the post. It's a CORS related issue so both 100 and 103 shall work in the same way.

推荐答案

我可以复制,在最新的稳定和TP上,我确实打开了this report.

在那份报告中引用我自己的话:

问题似乎在于访问BLOB数据的FETCH请求要经过跨域判断,但是BLOB本质上应该是同源的,因为它应该是"在内存中". 对于从data:URL创建的Worker,以及从file://Document中的BLOB:URL创建的Worker,都会发生这种情况.

奇怪的是,它对于不透明的来源iframe(Sandbox 或data:URL)似乎工作得很好.

不幸的是,由于Safari仍然不支持传输ReadableStream个对象,因此似乎没有任何好的解决方法.

最好的办法显然是从一开始就避免不透明的来源,但如果不可能,更好的解决办法是将文件从主线程读取到ArrayBuffer对象,然后将ArrayBuffer传输给您的工人,然后在那里传输decode it.I/O工作仍应并行完成,因此希望它不会阻塞您的用户界面.

/**
 * For this live Snippet, we use a data: URI instead of file:// + blob:
 * The same issue normally happens here.
 *
 * Side note:
 * Do not create a new Worker for every new File.
 * Start only one and reuse it.
 */
const workerdata = encodeURIComponent(document.querySelector('#worker').textContent);
const worker = new Worker("data:text/javascript," + workerdata);
worker.onmessage = ({ data }) => console.log(data);
async function on_change(evt) {
  const buffer = await evt.target.files[0].arrayBuffer();
  worker.postMessage(buffer, [buffer]);
};
<script id="worker" type="javascript/worker">
  self.onmessage = function(evt) {
    var buffer = evt.data;
    postMessage(new TextDecoder().decode(buffer));
  };
</script>
<input id="fileselector" type="file" onchange="on_change(event)">

Javascript相关问答推荐

在时间轴完整日历中显示日期标题

为什么getRecord()会因为与_logger相关的错误而失败?(使用Hedera SDK)

有什么(最佳)方法可以从模块中获取脚本模块的多姆元素吗?

微软Edge编辑和重新发送未显示""

切换时排序对象数组,切换不起作用

在grafana情节,避免冲突的情节和传说

虚拟滚动实现使向下滚动可滚动到末尾

Javascript json定制

为什么useState触发具有相同值的呈现

如果Arrow函数返回函数,而不是为useEffect返回NULL,则会出现错误

使用POST请求时,Req.Body为空

不能将空字符串传递给cy.containes()

WhatsApp Cloud API上载问题:由于MIME类型不正确而导致接收&Quot;INVALID_REQUEST";错误

如何将未排序的元素追加到数组的末尾?

400 bad request error posting through node-fetch

在css中放置所需 colored颜色 以填充图像的透明区域

使用自动识别发出信号(&Q)

使用可配置项目创建网格

在HTML中使用meta标记来指定定制元数据以用于使用JavaScript进行检索是不是一个坏主意?

将Windows XP转换为原始数据以在html前端中显示