Несколько асинхронных загрузок файлов с фрагментацией в веб-API ASP.Net

Я прочитал ряд тесно связанных вопросов, но не тот, который точно соответствует этому. Если это дубликат, пожалуйста, пришлите мне ссылку.

Я использую угловую версию библиотеки flowjs для загрузки файлов HTML5 (https://github.com/flowjs/ng-flow). Это работает очень хорошо, и я могу загружать несколько файлов одновременно кусками по 1 МБ. Существует контроллер файлов веб-API ASP.Net, который принимает их и сохраняет на диске. Хотя я могу сделать эту работу, я не делаю это эффективно и хотел бы знать лучший подход.

Во-первых, я использовал MultipartFormDataStreamProvider в асинхронном методе, который отлично работал, пока файл загружался одним фрагментом. Затем я переключился на использование FileStream для записи файла на диск. Это также работало, пока куски поступали в порядке, но, конечно, я не могу на это полагаться.

Затем, просто чтобы увидеть, как это работает, я записал куски в отдельные файловые потоки и объединил их постфактум, отсюда и неэффективность. Файл размером 1 ГБ будет генерировать тысячу фрагментов, которые необходимо будет прочитать и перезаписать после завершения загрузки. Я мог бы хранить все фрагменты файлов в памяти и сбрасывать их после загрузки, но боюсь, что сервер взорвется.

Кажется, должно быть хорошее асинхронное решение этой дилеммы, но я не знаю, что это такое. Одной из возможностей может быть использование async/await для объединения предыдущих фрагментов при записи текущего фрагмента. Другим может быть использование Begin/EndInvoke для создания отдельного потока, чтобы манипуляции с файлами на диске обрабатывались независимо от чтения потока из HttpContext, но это будет зависеть от ThreadPool, и я боюсь, что созданные потоки будут необоснованно прекращены. когда мой контроллер MVC вернется. Я мог бы создать FileWatcher, который работал бы полностью независимо от ASP.Net, но это было бы очень неуклюже.

Итак, мои вопросы: 1) есть ли уже простое решение, которое мне не хватает? (похоже, должно быть) и 2), если нет, то каков наилучший подход к решению этой проблемы в рамках веб-API?

Спасибо, Боб


person bob    schedule 07.05.2014    source источник


Ответы (2)


Я не знаком с такой загрузкой по частям, но я считаю, что это должно работать:

Это не обрабатывает ситуации, когда загрузка неожиданно прерывается. Такое решение обычно включает выделение/запись временного файла (со специальным расширением), а затем перемещение/переименование этого файла после прибытия последнего фрагмента.

Не забудьте убедиться, что запись вашего файла на самом деле асинхронно.

person Stephen Cleary    schedule 07.05.2014
comment
Это звучит идеально! Я не знал, что это можно сделать. Надеюсь, я смогу вернуться к этому коду сегодня днем ​​и попробовать его. Спасибо! - person bob; 07.05.2014
comment
Я пробовал это, но оказалось, что вы не можете записывать фрагменты не по порядку, не вызывая исключения. Джон Скит говорит об этом в этом вопросе tinyurl.com/kelqk9k. - person bob; 13.05.2014
comment
Невозможно вставить. Я предлагаю перезаписать. Он должен работать. - person Stephen Cleary; 13.05.2014
comment
Извините, я забыл вернуться и отметить это как правильный ответ. Он отлично работал, когда я реализовал его правильно. - person bob; 16.06.2014
comment
@Bob - Пытаюсь сделать то же самое здесь. Является ли ваше успешное решение общедоступным? Можно использовать пример кода, чтобы помочь мне начать работу. - person Herb Caudill; 25.08.2014

Используя ответ @Stephen Cleary и эту тему: https://github.com/flowjs/ng-flow/issues/41 Мне удалось создать реализацию ASP.NET Web Api и загрузить ее для тех, кто все еще задается вопросом об этом вопросе, таких как @Herb Caudill.

https://github.com/samhowes/NgFlowSample/tree/master.

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

Я добавлю это в примеры Flow по адресу: https://github.com/flowjs/flow.js/tree/master/samples

person Sam    schedule 01.10.2014
comment
FWIW, у меня недостаточно репутации, но это не уважительная причина. Ответы только по ссылке также не приветствуются. Но спасибо за помощь; к нашим правилам нужно время, чтобы привыкнуть. - person Veedrac; 01.10.2014