Браузер Edge зависает при выборе файлов для загрузки, если каталог содержит более 768 файлов - PullRequest
0 голосов
/ 29 августа 2018

У меня есть веб-приложение, которое позволяет пользователю загружать файлы DICOM и Non-DICOM. Я использую JavaScript, HTML5, Webkitdirectory и Datatable для заполнения выбранных файлов в пользовательском интерфейсе. Проблема, с которой я сталкиваюсь, -

Если папка содержит более 768 файлов DCM (если быть точным), браузер Edge зависает и пользователь не может выполнять никаких операций, пока пользователь не нажмет кнопку «восстановить эту страницу». Размер файла DCM и число исследований не имеют значения.

Несколько замечаний:

  • Чтение 1

Общее количество исследований: 4, Общее количество файлов DCM: 768, Общий размер папки: ~ 500 МБ, время отображения в пользовательском интерфейсе: 40 секунд

  • Чтение 2

Общее количество исследований: 5, Общее количество файлов DCM: 769, Общий размер папки: ~ 500 МБ, время отображения в пользовательском интерфейсе: зависание браузера

  • Чтение 3

Общее количество исследований: 2, Общее количество файлов DCM: 768, Общий размер папки: ~ 30 МБ, время отображения в пользовательском интерфейсе: 40 секунд

  • Чтение 4

Общее количество исследований: 3, Общее количество файлов DCM: 769, Общий размер папки: ~ 30 МБ, время отображения в пользовательском интерфейсе: зависание браузера .

Примечание. Это работает как брелок в Chrome And 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);

Анализ:

  • Браузер Edge зависает после регистрации « Начало чтения » 20-25 раз, тогда как « Завершенное чтение » никогда не регистрируется.
  • Я попытался проверить, работает ли браузер эффективно, если мы уменьшим нагрузку на браузер, добавив некоторую задержку после чтения подмножества файлов. Так что он может начать обработку нескольких файлов, и пользователь может увидеть некоторый прогресс. Но это также, похоже, не работает в соответствии с ожиданиями. В конечном итоге это поведение влияет на общее время, необходимое для отображения всех файлов в пользовательском интерфейсе.
  • Я попытался просмотреть файл DICOMDIR, но он не включает всю информацию, которую мы отображаем в сетке исследования, такую ​​как части тела, название учреждения, имя врача, а также UID изображения, кадры изображения отсутствуют. Чтобы получить этот материал, нам нужно проанализировать каждый файл DICOM для каждого исследования, чтобы найти недостающую информацию. Для чтения файла нам нужен доступ к файловой системе пользователя, чтобы получить полный путь к файлу. Но это невозможно из-за JavaScript, из соображений безопасности JQuery.

Я полагаю, это может быть связано с памятью браузера или стеком вызовов функций readAsArrayBuffer будет генерировать событие onload после его завершения чтение.

Любой обходной путь или любая идея, если это проблема с самим браузером MS Edge?

1 Ответ

0 голосов
/ 29 августа 2018

Мне интересно, какова ваша _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)
  }
}

Другая лучшая вещь может состоять в том, чтобы переместить это в веб-работника и отправить сообщение в него

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))
...