简体   繁体   English

通过Resposne发送内存中生成的.PDF文件

[英]Send .PDF file generated in memory via Resposne

So I have problem with Resposne file. 所以我有Resposne文件问题。 I can send some file but it is corrupted. 我可以发送一些文件,但文件已损坏。 I know my pdf librabry works fine (checked on console app) 我知道我的pdf librabry可以正常工作(已在控制台应用上检查)

    public void Get(ClaimExportRequest exportRequest)
    {
               var str = ExportToPdf(claimDataTable);
            using (var streams = new MemoryStream(str))
            {
                base.Response.AddHeader("Content-Disposition", "attachment; filename=report.pdf");
                base.Response.AddHeader("Content-Length", str.Length.ToString(CultureInfo.InvariantCulture));
                base.Response.ContentType = "application/octet-stream";
                streams.WriteTo(base.Response.OutputStream);
            }
            base.Response.EndRequest(true);
    }


    public byte[] ExportToPdf(DataTable dt)
    {

        var mem = new MemoryStream();
        var doc = new Document(new Rectangle(100f, 300f));
        PdfWriter.GetInstance(doc, mem);
        doc.Open();
        doc.Add(new Paragraph("This is a custom size"));
        return mem.ToArray();
    }

I have another part that creates CSV file and that one is fine! 我还有另一部分创建CSV文件,那很好!

        using (var streamOfCsvString = 

GenerateStreamFromString(csvBodyFromDt))
            {
                base.Response.UseBufferedStream = true;
                base.Response.AddHeader("Content-Disposition", "attachment; filename=data.csv");
                base.Response.AddHeader("Content-Length", streamOfCsvString.Length.ToString(CultureInfo.InvariantCulture));
                base.Response.ContentType = "text/csv";
                streamOfCsvString.CopyTo(base.Response.OutputStream);
            }
  base.Response.EndRequest(true);

I tried that method too with changed data to pdf. 我也尝试过将数据更改为pdf的方法。

Any idea what is wrong in first Get? 知道第一个Get怎么了吗? I know some lines are unnesesery but i tried everything that I found 我知道有些线是不必要的,但我尝试了发现的所有内容

Client 客户

 downloadURL: function(url) {
    var hiddenIFrameID, iframe;
    hiddenIFrameID = 'hiddenDownloader';
    iframe = document.getElementById(hiddenIFrameID);
    if (iframe === null) {
      iframe = document.createElement('iframe');
      iframe.id = hiddenIFrameID;
      iframe.style.display = 'none';
      document.body.appendChild(iframe);
    }
    return iframe.src = url;
  }

EDIT 编辑

I made code that creates this same file at harddrive to check 我编写了在硬盘上创建相同文件的代码以进行检查

  var doc = new Document(new Rectangle(100f, 300f));
            using (var fileStream = new FileStream("c:\\my.pdf", FileMode.Create))
            {

                PdfWriter.GetInstance(doc, fileStream);
                doc.Open();
                doc.Add(new Paragraph("This is a custom size"));
                base.Response.AddHeader("Content-Disposition", "attachment; filename=report.pdf");
                base.Response.AddHeader("Content-Length",
                    fileStream.Length.ToString(CultureInfo.InvariantCulture));
                base.Response.ContentType = "application/octet-stream";
                fileStream.CopyTo(base.Response.OutputStream); //WriteTo 
                doc.Close();
            }

            base.Response.EndRequest(true);

File is fine but, when doc.Close() is missing then file on the hard drive is corrupted. 文件很好,但是,当缺少doc.Close()时,硬盘驱动器上的文件已损坏。 But on the server side now I get 0 kB files (empty files) 但是现在在服务器端,我得到了0 kB文件(空文件)

From your example code, simply adding the doc.Close() did the trick for me. 从您的示例代码中,只需添加doc.Close()就可以了。

public byte[] ExportToPdf(DataTable dt)
{

    var mem = new MemoryStream();
    var doc = new Document(new Rectangle(100f, 300f));
    PdfWriter.GetInstance(doc, mem);
    doc.Open();
    doc.Add(new Paragraph("This is a custom size"));
    doc.Close();
    return mem.ToArray();
}

Edit: Like I said on my comment, you should enclose the MemoryStream in a using, like this: 编辑:就像我在评论中说的那样,您应该将MemoryStream封装在using中,如下所示:

public byte[] ExportToPdf(DataTable dt)
{
    using (var mem = new MemoryStream())
    {
        var doc = new Document(new Rectangle(100f, 300f));
        PdfWriter.GetInstance(doc, mem);
        doc.Open();
        doc.Add(new Paragraph("This is a custom size"));
        doc.Close();
        return mem.ToArray();
    }
}

Your code should look like this: 您的代码应如下所示:

using (var dataStream = ...)
{
    ...
    dataStream.CopyTo(base.Response.OutputStream);  
}
base.Response.EndRequest(true);

The end of the using block will Flush , Close and then Dispose the dataStream . using块的末尾将进行FlushClose ,然后Dispose dataStream The call to Flush will make sure any data still sitting in a buffer will be copied over, instead of waiting for potentially more data. Flush的调用将确保将仍然保留在缓冲区中的所有数据复制过来,而不是等待潜在的更多数据。 EndRequest should be called only after the data has been fully written to the OutputStream , so it should be called after the using block that will Flush the dataStream . 仅在将数据完全写入OutputStream之后才调用EndRequest ,因此应在将Flush dataStreamusing块之后调用dataStream

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM