Потоковый PDF не удается - файл не найден

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

Затем на двух разных страницах приложения у нас есть сетка, в которой отображается список вложений для записи. В сетке находятся кнопки ссылок, которые позволяют пользователю открыть данное вложение. Кнопка ссылки вызывает событие команды, передавая идентификатор вложения в качестве аргумента. В обработчике события команды мы получаем идентификатор из аргумента, используем его для извлечения вложения из службы в виде байтового массива, а затем перезаписываем объект ответа для возврата вложения. Вот код:

byte[] byteFile = DataHandler.GetAttachmentDocument(selectedAttachmentID);
if (DataHandler.sErrorMsg != "")
{//Error trying to retrieve file...
    this.DisplayMessageBox(DataHandler.sErrorMsg);
}
else
{//File retrieved...
    Response.Clear();
    Response.Buffer = true;

    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;filename=" + lblAttachmentName.Text);

    Response.Charset = "";
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.BinaryWrite(byteFile);
    Response.Flush();
    Response.Close();
    Response.End();
}

Теперь этот точно такой же код отлично работает на одной странице и не работает на другой. В обоих случаях, когда нажата кнопка и отображается диалоговое окно загрузки, нажмите кнопку "Открыть", и откроется окно Adobe Reader. На рабочей странице в окне читателя отображается запрошенный документ, но на другой странице из окна читателя мы получаем сообщение об ошибке: There was an error opening this document. This file cannot be found. Запустив в отладчике, мы можем пройти и увидеть, что мы получаем одинаковое количество байтов в byteFile, и что мы проходим полный метод без ошибок.

Мы немного погуглили по этому поводу и попробовали несколько вариантов этого кода, но безуспешно. Несколько вещей, которые я знаю, мы пытались изменить тип контента на поток октетов, добавить длину контента в заголовок, изменить буфер на false, удалить атрибут размещения контента. Единственная заметная разница заключалась в удалении атрибута размещения содержимого, в этом случае документ отображался, но отображался в исходном окне, а не в отдельном окне Adobe Reader. Еще одна идея, которая была предложена, но пока не опробована, заключается в том, чтобы извлечь сетку и связанную логику из веб-элемента управления, который затем можно будет повторно использовать на обеих страницах. Любые другие предложения?

2 ответа

Решение

Хотя нам никогда не удавалось точно определить причину проблемы, мы решили, что она, по крайней мере, в некоторой степени зависит от пользователя / компьютера. Таким образом, наша лучшая догадка - это какой-то странный конфликт или проблема с кэшированием на стороне клиента.

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

Затем мы перешли на страницы, которые обслуживают вложения, и изменили наши шаблоны сетки с кнопок ссылок с аргументами команд на гиперссылки с URL-адресом навигации, привязанным к пути новой страницы + аргументы строки запроса и целью _blank,

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

Спасибо Леону за подсказку. Хотя это не решило проблему, это помогло нам немного очистить наш код.

Не используйте Response.Close() и Response.End(). Flush() достаточно.

И вот почему: http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx

Другие вопросы по тегам