12

SQLデータベースにいくつかのファイルが保存されています。ASP.NET MVC3 フォームでは、次の 2 つのリンクが表示されます。

このファイルを表示 | このファイルをダウンロード

これらのリンクは、対応するアクション メソッドに移動します。ダウンロードは期待どおりに機能します。リンクをクリックすると、ブラウザーに保存ダイアログが強制的に表示されます。ただし、表示により重複した Content-Disposition ヘッダーがブラウザーに送信されるため、Chrome ではエラーが発生し、Firefox では空のページが表示されます。

[ActionName("display-file")]
public virtual ActionResult DisplayFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        Response.AddHeader("Content-Disposition", 
            string.Format("inline; filename={0}", file.Name));
        return File(file.Content, file.MimeType, file.Name);
    }
}

[ActionName("download-file")]
public virtual ActionResult DownloadFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        return File(file.Content, file.MimeType, file.Name);
    }
}

以下は、表示アクションのためにブラウザーに送信される 2 つのヘッダーです。

Content-Disposition: inline; filename=name-of-my-file.pdf
Content-Disposition: attachment; filename="name-of-my-file.pdf"

ファイル名を二重引用符で囲むようにカスタム content-disposition ヘッダーを変更しようとしましたが、それでも 2 つのヘッダーがブラウザーに送信されました。また、カスタム ヘッダーを追加する前に Content-Disposition ヘッダーを削除しようとしましたが、FileContentResult が返された後に添付ヘッダーが追加されているようです。

このコードは以前は機能していました。昨日テストを実行したところ、Chrome または Firefox で動作しなくなっていることに気付きました。これは、ブラウザの更新が原因である可能性があります。IE8 と Safari は引き続きファイルを正しく開きます。

アップデート

ありがとう、ダーリン、あなたは正しいです。あなたが答えた別の質問のために、実際にこのアプローチを使用しました。

これが最終的にどのように解決されたかについてもう少し詳しく説明します。表示ファイル リンクのカスタム ルートがあります。

context.MapRoute(null,
    "path/to/display-file-attachment/{fileId}/{fileName}",
    new
    {
        area = "AreaName",
        controller = "ControllerName",
        action = "DisplayFile",
    }
);

ページ上のハイパーリンクは、ファイル名をルート パラメーターを介してアクション メソッドに渡すため、既に URL の一部になっています。したがって、ユーザーがファイルをダウンロードすることを決定したとき (ブラウザの PDF ビューアで保存アイコンをクリックして)、ファイル名をシステムのものと一致させるために、カスタム content-disposition ヘッダーを追加する必要はありませんでした。したがって、これを使用しました:

[ActionName("display-file")]
public virtual ActionResult DisplayFile (Guid fileId, string fileName)
{
    var file = _repos.GetFileInfo(fileId);
    if (file != null)
    {
        // no custom content-disposition header, and no 3rd fileName argument
        return File(file.Content, file.MimeType);
    }
}
4

1 に答える 1

29

オーバーロードを使用するとFile(byte[] contents, string mimeType, string fileName)Content-Dispositionヘッダーが で応答に自動的に追加されるため、再度attachment追加する必要はありません。inline次のオーバーロードを使用して、ヘッダーFile(byte[] contents, string mimeType)を手動で追加できます。Content-Disposition

[ActionName("display-file")]
public virtual ActionResult DisplayFile(Guid fileId)
{
    var file = _repos.GetFileInfo(fileId);
    var cd = new ContentDisposition
    {
        Inline = true,
        FileName = file.Name
    };
    Response.AddHeader("Content-Disposition", cd.ToString()); 
    return File(file.Content, file.MimeType);
}

[ActionName("download-file")]
public virtual ActionResult DownloadFile(Guid fileId)
{
    var file = _repos.GetFileInfo(fileId);
    return File(file.Content, file.MimeType, file.Name);
}
于 2011-12-23T13:48:32.740 に答える