以下のコードは、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;
}
}
ありがとうございます。私はそれを試みたが、作成されたバックアップコピーが壊れていてパイプではない。私は質問を更新しました。 – Andrus
@Andrus:ReadToEnd()を使用しているからです。チャンクを読み込み、レスポンスに書き込んだり(おそらくWriteではなくBinaryWriteを使う)、flushメソッドを呼び出し、ストリームが終了するまですべてを繰り返すというループでプロセスからの出力を読み込むことを検討してください。 –