使用Process()将输入流写入另一个流

本文关键字:另一个 输入流 Process 使用 | 更新日期: 2023-09-27 18:11:12

我正在编写一个程序,该程序需要接受一个输入流,然后将其通过一个进程,然后输出一个新的流。这是用于使用由xml和xsl组成的流,并通过wkhtmltopdf.exe将其转换为pdf,并将pdf作为流输出。如有任何帮助,不胜感激。

编辑以添加代码和更好的理解:

进入函数我发送一个MemoryStream作为参数,我返回字节[]。我目前的代码看起来像这样,但它没有功能,因为我试图弄清楚如何接受流输入,转换它,然后再次返回它作为一个新的流。

code

public byte[] WKHtmlToPdf(MemoryStream inputStream)
{
        var fileName = " - ";
        _workingDirectory = ""; ''there is a directory here but contains company name
                                ''so I removed it
        _wkhtmlexe = wkhtmltopdf.exe";
        var p = new Process();
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.FileName = _wkhtmlexe;
        p.StartInfo.WorkingDirectory = _workingDirectory;
        StreamWriter inpuStreamWriter = new StreamWriter(inputStream);
        inpuStreamWriter = p.StandardInput;
        StreamReader outpStreamReader = p.StandardOutput;
        string switches = "";
        switches += "--print-media-type ";
        switches += "--margin-top 10mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
        switches += "--page-size Letter ";
        p.StartInfo.Arguments = switches + " " + inputStream + " " + fileName;
        p.Start();


        inpuStreamWriter.Write();
        //read output
        byte[] buffer = new byte[32768];
        byte[] file;
        using (var ms = inputStream)
        {
            while (true)
            {
                int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
                if (read <= 0)
                {
                    break;
                }
                ms.Write(buffer, 0, read);
            }
            file = ms.ToArray();
        }
        // wait or exit
        p.WaitForExit(60000);
        // read the exit code, close process
        int returnCode = p.ExitCode;
        p.Close();
        return returnCode == 0 ? file : null;
    }

使用Process()将输入流写入另一个流

您使用process的方法有部分错误。您可以从现有的html文件创建新的pdf文件,但您必须使用两个临时文件(一个用于html,第二个用于pdf输出)。在此场景中,工作流程将是:1)将记忆流保存为临时html文件2)运行新的进程(没有流重定向)-它产生新的PDF文件3)返回新的pdf文件作为流4)清理临时文件一旦你完成

你可以使用PInvoke直接使用libwkhtmltox

或(最好的)

你可以使用现有的解决方案,例如Pechkin,它为你做所有的PInvoke和本地合作与libwkhtmltox库:Pechkin使用

找到了解决问题的方法

private static void GeneratePdfFromStream()
    {
        var ms = xml_and_xsl_to_html();
        File.WriteAllBytes(Constants.FilesResultHtml, ms.ToArray());
        var printer = new Printer();
        var pdfStream = printer.GeneratePdf(new StreamReader(ms, Encoding.GetEncoding(850), false));
        File.WriteAllBytes(Constants.FilesResultPdf, pdfStream.ToArray());
    }

变量ms是从XslCompiledTransform()函数返回的内存流。然后将其传递给编码页850的streamReader中的GeneratePdf。函数看起来像这样:

public MemoryStream GeneratePdf(StreamReader html)
    {
        html.BaseStream.Position = 0;
        var pdf = new MemoryStream();
        using (html)
        {
            Process p;
            var psi = new ProcessStartInfo
            {
                FileName = @"C:'wkhtmltopdf'wkhtmltopdf.exe",
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                Arguments = Switches() + "-q -n --enable-smart-shrinking " + " - -"
            };
            p = Process.Start(psi);
            try
            {
                if (p != null)
                {
                    var stdin = p.StandardInput;
                    stdin.AutoFlush = true;
                    stdin.Write(html.ReadToEnd());
                    stdin.Dispose();
                }
                CopyStream(p.StandardOutput.BaseStream, pdf);
                Console.WriteLine(  p.StandardOutput.CurrentEncoding.CodePage);
                p.StandardOutput.Close();
                pdf.Position = 0;
                p.WaitForExit(10000);
                return pdf;
            }
            catch
            {
                return null;
            }
            finally
            {
                if (p != null) p.Dispose();
            }
        }
    }