2012-03-24 7 views
0

以下のコードは、LinuxのApache Mono MVC2 WebアプリケーションのブラウザからPostgreSQLデータベースバックアップを保存するために使用します。Monoでブラウザにstdoutをパイプする方法Apache MVC2アプリケーション

ファイル転送が開始されるまでにバックアップが完了するまでに時間がかかります。 pg_dumpはfileではなく標準出力に書き込むことができます。 コントローラに、一時ファイルを作成せずに標準出力をブラウザに送るように強制するには? または進行状況インジケーターをユーザーに表示する方法はありますか?

[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; 
     } 
    } 

答えて

0

あなたはRedirectStandardOutputを使用してストリーミングして、(おそらくよく知っているので、AJAXや、と組み合わせて)いくつかの進歩を示すために、あなたにできProcess.StandardOutputから読み取るために、標準出力をリダイレクトすることができます。

+0

ありがとうございます。私はそれを試みたが、作成されたバックアップコピーが壊れていてパイプではない。私は質問を更新しました。 – Andrus

+0

@Andrus:ReadToEnd()を使用しているからです。チャンクを読み込み、レスポンスに書き込んだり(おそらくWriteではなくBinaryWriteを使う)、flushメソッドを呼び出し、ストリームが終了するまですべてを繰り返すというループでプロセスからの出力を読み込むことを検討してください。 –

0

一時バッファ(ファイルまたはメモリストリーム)に出力ストリームを書き込み、別のスレッドがsingnalR?ここでは、signalRを示す良いビデオがあります: http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR

ストリームコンテンツの変更に応じてリアルタイムでブラウザにデータを送信することができます。また、破損があったと言いますが、これは私が何度も何度も噛んでいるだけなので、同じ文字エンコーディングで出力をシリアライズしてデシリアライズしてください。

関連する問題