«Указанный метод не поддерживается» ошибка с iTextSharp - PullRequest
4 голосов
/ 07 июня 2011

Я использую iTextSharp для создания PDF-файлов. Ниже я добавил тестовый метод, который делает простую страницу с одним абзацем. Это работает, PDF генерируется, однако, через некоторое время после того, как PDF отправляется в браузер, я получаю NotSupportedException в журнале событий (или если я сам ловлю их из Application_Error). Вот самый простой код, который вызывает эту ошибку:

public FileStreamResult TestPdf()
{
  using (var ms = new MemoryStream())
  {
    using (var document = new Document())
    {
      PdfWriter.GetInstance(document, ms);
      document.Open();
      document.Add(new Paragraph("Hello World!"));
      document.Close();
    }
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;filename=test.pdf");
    Response.Buffer = true;
    Response.Clear();
    Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
    Response.OutputStream.Flush();
    Response.End();
  }
  return new FileStreamResult(Response.OutputStream, "application/pdf");
}

И выдает ошибку (через некоторое время после завершения запроса)

Exception information: 
Exception type: NotSupportedException 
Exception message: Specified method is not supported.
at System.Web.HttpResponseStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase response)
at System.Web.Mvc.FileResult.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<>c__DisplayClass1e.<InvokeActionResultWithFilters>b__1b()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Есть идеи, как мне это исправить? Есть проблема с библиотекой или что-то еще?

Спасибо!

Изменить:

Чтобы решить эту проблему, вместо возврата FileStreamResult я смог использовать FileContentResult вместо этого с помощью метода File контроллера. Вот рабочий код:

public ActionResult TestPdf()
{
  using (var ms = new MemoryStream())
  {
    using (var document = new Document())
    {
      PdfWriter.GetInstance(document, ms);

      document.Open();
      document.Add(new Paragraph("Hello World!"));
      document.Close();
    }
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;filename=test.pdf");
    Response.Buffer = true;
    Response.Clear();        
    return File(ms.ToArray(), "application/pdf");
  }
}

1 Ответ

1 голос
/ 07 июня 2011

В этой строке есть ошибка:

Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);

Используйте ToArray вместо GetBuffer.Например:

var bytes = ms.ToArray();
Response.OutputStream.Write(bytes, 0, bytes.Length);

MemoryStream.GetBuffer возвращает выделенные байты, а не заполненные байты.

Пример проблемы:

using (var memoryStream = new MemoryStream())
{
    memoryStream.WriteByte(1);
    var length = memoryStream.ToArray().Length; // returns 1
   var bufferLength = memoryStream.GetBuffer().Length; // returns 256
}

Хотя добавлен один байт, GetBuffer вернет 256 байт.

...