C# 从MemoryStream打印pdf文档

C# 从MemoryStream打印pdf文档,c#,pdf,itextsharp,C#,Pdf,Itextsharp,我需要打印我修改过的pdf文档,而不将其保存回新的pdf文档。下面的代码可以正常工作。然而,我想做的是完全不同的,我同时有一个大脑滞后,看不到解决办法 我的代码示例 byte[] result; using (MemoryStream ms = new MemoryStream()) { PdfReader pdfReader = new PdfReader("c:\\templatePdf.pdf"); PdfStamper pdfStamper = new PdfStamp

我需要打印我修改过的pdf文档,而不将其保存回新的pdf文档。下面的代码可以正常工作。然而,我想做的是完全不同的,我同时有一个大脑滞后,看不到解决办法

我的代码示例

byte[] result;

using (MemoryStream ms = new MemoryStream())
{
    PdfReader pdfReader = new PdfReader("c:\\templatePdf.pdf");
    PdfStamper pdfStamper = new PdfStamper(pdfReader, ms);

    /* abbreviated but here I alter the template pdf */

    pdfStamper.FormFlattening = true;
    pdfStamper.Close();
    result = ms.GetBuffer();
}

/* Instead of saving a new file I would rather like to print
   the altered template pdf in memory and then discard it */
using (FileStream fs = File.Create("C:\\Test.pdf"))
{
    fs.Write(result, 0, (int)result.Length);
}

Process process = new Process();
process.StartInfo.FileName = "C:\\Test.pdf";
process.StartInfo.Verb = "printto";
process.StartInfo.Arguments = "\"" + ppr_PrinterDropDown.Text + "\"";
process.Start();
File.Delete("C:\\Test.pdf");

如果您使用的是基于文件的API,那么在没有文件的情况下,您将很难做到这一点。您可能可以设置一个命名管道服务器,但坦率地说,这是一个巨大的麻烦。然而,我很想四处寻找一个支持打印的完全管理的PDF库。但最终。。。文件系统到底有什么危害?可能不是很多。不过,我可能会建议一些调整:

  • 使用临时区域(
    Path.GetTempPath()
    ),而不是
    C:\Test
  • 在删除文件之前,请等待进程完成

  • 首先我们需要写入内存流,然后借助内存流方法“WriteTo”,我们可以写入页面的响应,如下面的代码所示

       MemoryStream filecontent = null;
       filecontent =//CommonUtility.ExportToPdf(inputXMLtoXSLT);(This will be your MemeoryStream Content)
       Response.ContentType = "image/pdf";
       string headerValue = string.Format("attachment; filename={0}", formName.ToUpper() + ".pdf");
       Response.AppendHeader("Content-Disposition", headerValue);
    
       filecontent.WriteTo(Response.OutputStream);
    
       Response.End();
    

    FormName是给定的文件名,此代码将通过调用弹出窗口使生成的PDF文件可下载。

    这很简单。困难的部分是获取有关打印状态完成和总页码的有用信息

    var pq = LocalPrintServer.GetDefaultPrintQueue();
    var theJob = pq.AddJob();
    try{
        using(var js = theJob.JobStream){
            var buffer = File.ReadAllBytes("yourPathToPdf");
            js.Write(buffer,0,buffer.Length);
        }
        var done=false;
        while(!done)
        {
            pq.Refresh();
            theJob.Refresh();
            done = theJob.IsCompleted || theJob.IsDeleted || theJob.IsPrinted;
        }
    }
    catch(Exception ex){
        //handle this
    }
    finally{
        theJob?.Dispose();
        pq?.Dispose();
    }
    

    当然,这是假设您的打印机具有本机PDF支持。否则,您必须自己在客户端上执行渲染工作,并将其作为原始流发送。

    您应该使用
    result=ms.GetBuffer()
    -您应该使用
    ToArray()
    。否则你会有一堆尾随的空值。另外,使用
    File.WriteBytes
    或只使用
    MemoryStream.WriteTo
    使生活更简单。感谢您的评论@JonSkeet,但如果流程需要读取文件名,我将如何在流程中处理它?(我的意思是这样我可以打印pdf);)这并不是一个答案——它只是对现有代码的旁白。根据马克的回答,我怀疑你们仍然需要使用一个文件。是的,你们两个可能都是对的。谢谢你的评论:)我一直在研究类似的东西(更新pdf表格,然后打印,而不将中间文件保存到磁盘)。你有没有想过不写磁盘就打印的方法?看起来答案似乎偏离了这个选项,但我想我会问。谢谢你的回答@MarcGravel。那可能是唯一的办法,至少我现在处理这个问题的方式找不到任何解决办法。我可能会寻找一些pdf库来帮助我解决问题,但我想我会采取简单的方法,只使用临时位置:)谢谢你的评论,尽管这个线程实际上已经很旧:)我可能会在得到更改并给你反馈后尝试一下。你所说的“页面响应”是什么意思?“响应”来自什么方法?