如果目录包含超过768个文件,边缘浏览器会在选择要上载的文件时冻结

问题描述 投票:-1回答:1

我有一个Web应用程序,允许用户上传DICOM和非DICOM文件。我使用JavaScript,HTML5,Webkitdirectory和Datatable来填充UI上的选定文件。我面临的问题是 -

如果该文件夹包含超过768个DCM文件(准确地说),则边缘浏览器会冻结,并且用户无法执行任何操作,直到用户点击“恢复此页面”按钮。 DCM文件的大小和数字研究无关紧要。

很少有观察到:

  • 阅读1

总研究数量:4,DCM文件总数:768,文件夹总大小:~500 MB,在UI上显示的时间:40秒

  • 阅读2

总研究数量:5,DCM文件总数:769,文件夹总大小:~500 MB,在UI上显示的时间:浏览器冻结

  • 阅读3

总研究数量:2,DCM文件总数:768,文件夹总大小:~30 MB,在UI上显示的时间:40秒

  • 阅读4

总研究数量:3,DCM文件总数:769,文件夹总大小:~30 MB,在UI上显示的时间:浏览器冻结。

注意:这项工作就像Chrome和Firefox中的魅力一样。

这是我为每个DICOM文件执行的代码(Inside forEach) -

var fileReader = new FileReader();
fileReader.onload = function(evt){
    console.log("Completed Reading");
    var arrayBuffer = fileReader.result;

    var byteArray = new Uint8Array(arrayBuffer);
    _parseDicom(byteArray);
    try {
        if (fileReader.readyState !== 2) {
            fileReader.abort();
        }
    }
    catch (err) {
        console.log('error occured: '+err);
    }
}
var blob = f.slice(0, 50000);
console.log("Starting to Read");
fileReader.readAsArrayBuffer(blob);

分析:

  • 记录“开始读取”20-25次后边缘浏览器冻结,而“完成读取”永远不会记录。
  • 如果我们通过在读取文件子集后添加一些延迟来减少浏览器的负载,我试图检查浏览器是否有效。这样它就可以开始处理少量文件,用户可以看到一些进展。但是这似乎也不符合预期。最终,这种行为会影响在UI上呈现所有文件所需的总时间。
  • 我试着查看DICOMDIR文件,但它不包括我们在研究网格中显示的所有信息,例如身体部位,机构名称,转诊医师名称也是图像UID,图像帧丢失。要获取这些东西,我们需要解析每个研究的每个DICOM文件以检索丢失的信息。对于读取文件,我们需要访问用户的文件系统来检索文件的完整路径。但由于JavaScript,JQuery的安全性原因,这是不可行的。

我相信这可能是由于浏览器内存或函数调用堆栈,因为readAsArrayBuffer一旦完成读取就会生成onload事件。

任何解决方法或任何想法,如果这是MS Edge浏览器本身的问题?

javascript webkit microsoft-edge
1个回答
1
投票

我很好奇你的_parseDicom剂量...如果它可以被优化以检查是否有一个神奇的数字来指示文件是否是DCM文件(我不知道DCM文件是什么)

也许您不应该在forEach循环中执行所有这些文件读取,因为它将并行读取所有文件,如果您一次执行一个文件,则可以优化内存。

async function doWork(fileList) {
  for (const file of FileList) {
    const res = new Response(file.slice(0, 50000))
    const arrayBuffer = await res.arrayBuffer()
    const byteArray = new Uint8Array(arrayBuffer)
    _parseDicom(byteArray)
  }
}

也许更好的是,如果你的_parseDicom可以接受一个流而不是一个字节数组

async function doWork(fileList) {
  for (const file of fileList) {
    const res = new Response(file.slice(0, 50000))
    const stream = res.body.getReader()
    await _parseDicom(stream)
  }
}

另一个最好的事情可能是将其移动到Web worker并将文件postMessage到它

es5解决方案

function doWork(files) {
  var file = files.pop()
  file && new Response(file.slice(0, 50000)).arrayBuffer(function(arrayBuffer){
     var byteArray = new Uint8Array(arrayBuffer)
     _parseDicom(byteArray)
     doWork(files)
  })
}

doWork(Array.from(fileList))
© www.soinside.com 2019 - 2024. All rights reserved.