2012-03-24 7 views
0

Code unten wird verwendet, um PostgreSql Datenbank-Backup von Browser in Apache Mono MVC2 Web-Anwendung in Linux zu speichern.wie stdout zum Browser in Mono Apache MVC2-Anwendung pipe

Es dauert lange, bis die Sicherung abgeschlossen ist, bevor die Dateiübertragung beginnt. pg_dump kann in die Standardausgabe anstatt in die Datei schreiben. Wie erzwinge ich Controller, um die Standardausgabe an den Browser zu übergeben, ohne eine temporäre Datei zu erstellen? Oder, wie man Fortschrittsanzeige dem Benutzer zeigt?

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

Update

Ich habe versucht, Code unten beantworten nach. Eine im Browser gespeicherte Sicherungskopie führt zum Absturz von pg_restore. Wie verwende ich binäres Schreiben oder etwas anderes, um ein korrektes Backup zu erstellen? Auch der Browser fordert Sie auf, erst zu speichern, nachdem pg_dump beendet wurde. Wie implementiert man Pipe, so dass Daten über das Internet übertragen werden, wenn pd_dump funktioniert?

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

Antwort

0

Sie können die Standardausgabe umleiten zu streamen RedirectStandardOutput und anschließend von Process.StandardOutput lesen, die Ihnen ermöglicht, einige Fortschritte zu zeigen (mit AJAX kombiniert oder so, die Sie wahrscheinlich gut kennen).

+0

Vielen Dank. Ich habe es versucht, aber Sicherungskopie erstellt ist beschädigt und nicht verrohrt. Ich habe die Frage aktualisiert. – Andrus

+0

@Andrus: Es ist, weil Sie ReadToEnd() verwenden. Erwägen Sie, die Ausgabe des Prozesses in einer solchen Schleife zu lesen: Lesen Sie einen Chunk, schreiben Sie ihn in die Antwort (möglicherweise mit BinaryWrite anstelle von Write), rufen Sie die Flush-Methode auf, wiederholen Sie alle, bis der Stream endet. –

0

Vielleicht schreiben Sie den Ausgabestrom in einen Temp-Puffer (Datei oder Speicher-Stream), während ein anderer Thread an den Browser mit SingnalR leitet? Hier ist eine gute Video-Demonstration SignalR: http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR

Es würde Ihnen erlauben, Daten an den Browser in Echtzeit zu senden, wie der Stream Inhalte ändern. Sie sagen auch, dass es Korruption gab, ich sage nur, weil es mich mehr als einmal gebissen hat, stellen Sie sicher, dass Sie Ihre Ausgabe mit der gleichen Zeichencodierung serialisiert und deserialisiert haben.