2009-08-24 3 views
8

Я использую ASP.NET MVC и имею длительный процесс. В частности, я создаю большой PDF-файл для загрузки.Длительный процесс, который вернет файл

Я понимаю основную концепцию:

  1. метод действий вызывается,
  2. Нового поток начал генерировать процесс
  3. возвратить представление, которое говорит пользователю (PDF) генерируется
  4. Использования AJAX для вызова сервера и запроса прогресса
  5. После того, как вы закончили, представьте файл пользователю для загрузки.

Части я не до конца понимаю, являются:

  • Управления нити через отдельный AJAX звонки. Мне, возможно, потребуется какой-то способ найти текущий поток и запросить статус. Есть ли статический контекст, который я могу содержать ссылку на поток? Я знаю о кэшировании данных в HttpContext.Application, это было бы подходящим для этого?
  • И как представить законченный файл. Создать временный файл и представить ссылку для загрузки? Или я могу сделать окончательный вызов AJAX, который возвращает файл?
+0

Отличный вопрос ... застрял в такой же ситуации! –

ответ

6

Каше очень хорошо подходит для этого. Только одно: убедитесь, что элемент кэширован никогда не удаляется во время выполнения процесса (для этого вы можете использовать ItemPriority.NotRemovable).

Вы можете сохранить файл на диске в папке temp или сохранить его в кеше в течение некоторого времени (это зависит).
Я лично не хочу загрязнять жесткий диск файлами, поэтому я бы сохранил файл в кеше (с помощью MediumPriority в течение нескольких минут). Но файл большой и может быть сгенерирован часто, вместо этого используйте базу данных файловой системы.

На клиенте, когда последний Ajax запрос возвращает результат (может выглядеть {прогресс: "100%", resultUrl: "http://your.url/Where/ToGet/TheFile.aspx?file=GUID-OR-CACHE-KEY"}) вы можете перенаправить браузер на URL при условии.
Он, в свою очередь, отобразит этот файл как двоичный результат.

Client редирект можно сделать с помощью JavaScript, как это:

location.href = response.resultUrl; 

Кстати, как вы генерировать PDF? NFOP?

+0

Спасибо за ответ. Я собираюсь дать эту попытку в ближайшее время, так что дайте знать, как я нахожусь. На данный момент у меня нет средств для генерации фактического PDF :( – jeef3

+0

Еще одна вещь, о которой я забыл упомянуть. На сайте ASP.NET MVC CodePlex есть AsynController. Это может быть полезно для вас. Я думаю, что он абстрагируется от потоковой передачи Задачи –

+0

О, ну, интересно, придется заглянуть в это. – jeef3

7

Это работает!

Вот что я сделал:

Шаг 1 & 2 - Действие Метод вызывается, долго выполняющиеся поток запускается

Когда мой метод действия вызывается, он генерирует уникальный идентификатор. Затем я создаю экземпляр класса PdfGenerator, создаю новый поток, который вызывает PdfGenerator.Generate и запускает его.

public class PdfGenerator 
{ 
    public string State; 
    public byte[] Data; 

    public void Generate() 
    { 
     // Generate PDF/Long running process 
     // Should update State as it goes 
     // ... 
     // Once finished, Data is populated with the binary byte[] 
    } 
} 

После того, как поток начал (или перед запуском) экземпляр генератора хранится в кэше:

HttpContext.Cache[guid] = generator; 

Я также прикрепить Guid к ViewData, так что это может быть ссылка на мой взгляд, скрипт.

Шаг 3 & 4 - Отображение и изменение статус/прогресс вид

Теперь, когда поток запущен и генерация PDF начала, я могу показать мой взгляд прогресса сценарий. Использование JQuery-х $.getJSON я могу опрашивать отдельные меры, чтобы найти статус генерации:

[OutputCache(Duration = 0, VaryByName = "none", NoStore = true)] 
public JsonResult CheckPdfGenerationStatus(string guid) 
{ 
    // Get the generator from cache 
    var generator = HttpContext.Cache[guid] as PdfGenerator; 

    if (generator == null) 
     return Json(null); 
    else 
     return Json(generator.State); 
} 

Мой взгляд сценарий интерпретирует JSon и отображает соответствующую информацию о ходе.

Шаг 5 - Present файл пользователю

После того, как генерация будет завершена, состояние генераторов устанавливается соответствующим образом и когда JQuery получает эту информацию, она может либо предоставлять ссылку, или непосредственно отправить файл с помощью javascripts location.href.

Способ действий, который устанавливает и возвращает файл просто получает генератор из кэша и возвращает вложенные байты []

public ContentResult DownloadPdf(string guid) 
{ 
    var generator = HttpContext.Cache[guid] as PdfGenerator; 

    if (generator == null) 
     return Content("Error"); 

    if (generator.State == "Completed") 
    { 
     return Content(generator.Data); 
    } 
    else 
    { 
     return Content("Not finished yet"); 
    } 
} 

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

Так что да, надеюсь, что кто-нибудь еще поможет сделать что-то подобное.

Смежные вопросы