2012-03-24 6 views
0

아래 코드는 Linux의 Apache Mono MVC2 웹 응용 프로그램의 브라우저에서 PostgreSql 데이터베이스 백업을 저장하는 데 사용됩니다.Mono Apache MVC2 응용 프로그램에서 브라우저에 stdout을 파이프하는 방법

파일 전송이 시작되기 전에 백업이 완료되는 데 시간이 오래 걸립니다. 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()를 사용하고 있기 때문입니다. 다음과 같은 루프에서 프로세스의 출력을 읽는 것을 고려하십시오. 청크 읽기, 쓰기 대신 응답 (BinaryWrite 사용) 작성, flush 메소드 호출, 스트림 종료까지 모두 반복 –

0

임시 버퍼 (파일 또는 메모리 스트림)에 출력 스트림을 쓰고 또 다른 스레드는 singnalR로 브라우저에 연결합니까? 다음은 signalR을 보여주는 좋은 동영상입니다. http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR

스트림 내용이 변경되면 실시간으로 브라우저에 데이터를 보낼 수 있습니다. 또한, 부패가 있다고 말하면서, 나는 이것이 단지 두 번 이상 나를 괴롭히는 원인이라고 말하고, 동일한 문자 인코딩으로 출력을 직렬화 및 비 직렬화해야합니다.

관련 문제