如何在Mono Apache MVC2应用程序中将stdout传递给浏览器

时间:2012-03-24 07:24:11

标签: c# asp.net-mvc postgresql mono mod-mono

以下代码用于在Linux中的Apache Mono MVC2 Web应用程序中从浏览器保存PostgreSql数据库备份。

在文件传输开始之前,备份需要很长时间才能完成。 pg_dump可以写入标准输出而不是文件。 如何强制控制器管道标准输出到浏览器而不创建临时文件? 或者如何向用户显示一些进度指示器?

[Authorize] 
public class BackupController : ControllerBase 
 { 
   [AcceptVerbs(HttpVerbs.Get)] 
   public ActionResult Backup() 
   { 
            var pinfo = new ProcessStartInfo(); 
            var fn = "temp.backup"; 
            pinfo.Arguments = " -f \"" + fn + "\" -Fc -h \"" + "myserver" + "\" -U \"" +                 "postgres" + " \"" + "mydb" + "\""; 
            pinfo.FileName = "/usr/lib/pgsql/pg_dump"; 
            pinfo.UseShellExecute = false; 
            using (var process = new Process()) 
            { 
                process.EnableRaisingEvents = true; 
                process.StartInfo = pinfo; 
                process.Start(); 
                while (!process.HasExited) 
                    Thread.Sleep(2000); 
                process.WaitForExit(); 
                if (process.ExitCode!=0) 
                  throw new Exception("error"); 
                process.Close(); 
            } 
            Response.ClearContent(); 
            Response.WriteFile(fn); 
            Response.End(); 
            System.IO.File.Delete(fn); 
            return null; 
        } 
} 

更新

我根据答案尝试了下面的代码。从浏览器保存的备份副本会导致pg_restore崩溃。如何使用二进制写或其他东西来创建正确的备份?此外,浏览器仅在pg_dump完成后提示保存。如果pd_dump工作,如何实现管道以便通过互联网传输数据?

[Authorize]
public class BackupController : ControllerBase
{
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Backup()
    {
        Response.ClearContent();
        Response.AddHeader("content-disposition", string.Format("attachment; filename=\"backup.backup\"");
        Response.ContentType = "application/backup";
        using (var process = new Process())
        {
            process.StartInfo.Arguments = " -ib -Z6 -Fc -h \"server\"";
            process.StartInfo.FileName = "/usr/lib/pgsql/pg_dump";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            Server.ScriptTimeout = 86400;
            process.Start();
            while (!process.HasExited)
            {
                var b = process.StandardOutput.ReadToEnd();
                Response.Write(b);
                Thread.Sleep(2000);
            }
            process.WaitForExit();
            if (process.ExitCode != 0)
            {
                return new ContentResult()
                {
                    Content = "Error " + process.ExitCode.ToString()
                };
            }
            var b2 = process.StandardOutput.ReadToEnd();
            Response.Write(b2);
            process.Close();
            Response.End();
            return null;
        }
    }

2 个答案:

答案 0 :(得分:0)

您可以使用RedirectStandardOutput将标准输出重定向到流,然后从Process.StandardOutput读取,这样您就可以显示一些进度(与AJAX一起使用,您可能知道的很好)。

答案 1 :(得分:0)

也许将输出流写入临时缓冲区(文件或内存流),而另一个线程通过singnalR管道到浏览器?这是一个展示signalR的好视频: http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR

它允许您在流内容发生变化时实时向浏览器发送数据。此外,你说有腐败,我只说这导致它不止一次,确保你使用相同的字符编码序列化和反序列化你的输出。