2012-03-24 2 views
0

Код ниже используется для сохранения резервной копии базы данных PostgreSql из браузера в веб-приложении Apache Mono MVC2 в Linux.Как подключить stdout к браузеру в приложении Mono Apache MVC2

Завершение резервного копирования занимает много времени, прежде чем начнется передача файлов. 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; 
     } 
    } 

ответ

0

Вы можете перенаправить стандартный вывод в поток с помощью RedirectStandardOutput, а затем читать Process.StandardOutput, которая позволяет вам показать некоторый прогресс (в сочетании с AJAX или так, что вы, вероятно, хорошо знаете).

+0

Спасибо. Я попробовал, но созданная резервная копия повреждена и не связана с каналами. Я обновил вопрос. – Andrus

+0

@ Andrus: Это потому, что вы используете ReadToEnd(). Рассмотрите возможность чтения вывода из процесса в таком цикле: прочитайте фрагмент, напишите его в ответ (возможно, используя BinaryWrite вместо Write), вызовите метод flush, повторите все, пока поток не закончится. –

0

Возможно, запись выходного потока в буфер темпа (поток файлов или памяти), а другой поток - в браузер с помощью singnalR? Вот хорошее видео, демонстрирующее сигналR: http://channel9.msdn.com/Shows/Web+Camps+TV/Damian-Edwards-and-David-Fowler-Demonstrate-SignalR

Это позволит вам отправлять данные в браузер в режиме реального времени по мере изменения содержимого потока. Кроме того, вы говорите, что есть коррупция, я только говорю, что это бит меня несколько раз, убедитесь, что вы сериализовали и десериализуете свой вывод с тем же кодированием символов.

Смежные вопросы