ASP.NET Web APIでダウンロードファイル名を設定する方法


140

私のApiControllerクラスには、サーバーによって作成されたファイルをダウンロードするための次のメソッドがあります。

public HttpResponseMessage Get(int id)
{
    try
    {
        string dir = HttpContext.Current.Server.MapPath("~"); //location of the template file
        Stream file = new MemoryStream();
        Stream result = _service.GetMyForm(id, dir, file);
        if (result == null)
        {
            return Request.CreateResponse(HttpStatusCode.NotFound);
        }
        result.Position = 0;
        HttpResponseMessage response = new HttpResponseMessage();
        response.StatusCode = HttpStatusCode.OK;
        response.Content = new StreamContent(result);
        return response;
    }
    catch (IOException)
    {
        return Request.CreateResponse(HttpStatusCode.InternalServerError);
    }
}

デフォルトのダウンロードファイル名がそのIDであることを除いて、すべてが完璧に機能しているため、ユーザーは毎回ダイアログとして保存するときに自分のファイル名を入力する必要があります。上記のコードでデフォルトのファイル名を設定する方法はありますか?


1
このメソッドの呼び出しに使用したコードを共有できますか?
Yasser Shaikh、

@Yasser-これはWeb APIコントローラーメソッドです。IISに着信したHTTPリクエストを介して呼び出され、それらを解析して、ルートを検索し、メソッドを呼び出すWeb APIを見つけます(もちろん、テストによっても呼び出されます)。
Dave Rael

GetMyForm()内で何が起こっていますか?ファイルをバイトのストリームに変換していますか?
MSIslam 2018

@MSIslam並べ替え。この関数は、ユーザーのフォームから情報を取得し、結果のストリームに変換する前にファイルを作成します。
泰-宋新

回答:


288

Content-Dispositionヘッダーを設定する必要がありますHttpResponseMessage

HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(result);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileName = "foo.txt"
};

21
"attachment"処理タイプについて知りたい場合
sfuqua

1
ここにファイルダウンロードする別の答えがあります。あなたが使用するかどうかは問題ではありませんSystem.Net.Mime.ContentDispositionContentDispositionHeaderValue?どちらか一方が最新であり、もう一方よりも優先されていますか?
ルミナス

@Luminous 1つの回答はActionResult、1つはのためHttpResponseMessage
weston

@ウェストンあなたの応答は私の質問に答えません。
ルミナス

4
@Luminous "重要ですか"および "もう1つは現在よりも優先されますか?" いいえ、ありません。1つはMVC用ActionResultで、もう1つはWebApi用ですHttpResponseMessage
ウェストン

27

編集:コメントで述べたように、私の答えはのようにエスケープする必要がある文字を考慮していません;。ファイル名にセミコロンが含まれる可能性がある場合は、受け入れられたDarinの回答を使用してください。

Response.AddHeaderを追加してファイル名を設定します

Response.AddHeader("Content-Disposition", "attachment; filename=*FILE_NAME*");

FILE_NAMEをファイルの名前に変更するだけです。


2
これは、質問者と同様の問題を解決するのに役立ちました。私の場合、「添付ファイル」を「インライン」に変更すると、IE8で問題のファイルタイプを常に開くオプションが表示されるので便利です。
スコット

2
エスケープはカバーしていません。ファイル名に;特別な意味を持つ何かが含まれている場合はどうなりますか?
サム

サム、私が3年前にこの回答を書いたとき、エスケープを処理するために必要な回答がわからなかった。これを指摘していただきありがとうございます。私の答えはエスケープの原因ではないことを説明したため、私の答えを編集しました。しかし、それは人々を助けているようだったので、私の答えを同じに保ちました。
KingPancake 2015年

8

ファイル名が適切にエンコードされていることを確認したいが、WebApi HttpResponseMessageも回避したい場合は、以下を使用できます。

Response.AddHeader("Content-Disposition", new System.Net.Mime.ContentDisposition("attachment") { FileName = "foo.txt" }.ToString());

ContentDispositionまたはContentDispositionHeaderValueを使用できます。どちらかのインスタンスでToStringを呼び出すと、ファイル名のエンコードが行われます。


6

これは参考になると思います。

Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName)

4
エスケープはカバーしていません。ファイル名に;特別な意味を持つ何かが含まれている場合はどうなりますか?
サム

3

content-dispositionヘッダーを応答に追加する必要があります。

 response.StatusCode = HttpStatusCode.OK;
 response.Content = new StreamContent(result);
 response.AppendHeader("content-disposition", "attachment; filename=" + fileName);
 return response;

3
エスケープはカバーしていません。ファイル名に;特別な意味を持つ何かが含まれている場合はどうなりますか?
サム

3

ASP.NET Core MVCを使用している場合、上記の回答は少し変更されています...

アクションメソッド(を返すasync Task<JsonResult>)で、次の行を追加します(returnステートメントの前の任意の場所)。

Response.Headers.Add("Content-Disposition", $"attachment; filename={myFileName}");

エスケープはカバーしていません。ファイル名に; または特別な意味を持つ他の何か?
コアラベア

2

これは行う必要があります:

Response.AddHeader("Content-Disposition", "attachment;filename="+ YourFilename)

2
エスケープはカバーしていません。ファイル名に;特別な意味を持つ何かが含まれている場合はどうなりますか?
サム

0

注:最後の行は必須です。

Access-Control-Expose-Headersを指定しなかった場合、UIでファイル名を取得できません。

FileInfo file = new FileInfo(FILEPATH);

HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileName = file.Name
};
response.Content.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

0

以前の回答を考慮すると、グローバル化された文字に注意する必要があります。

ファイル名が「Esdrújulaprendañame-güena.jpg」であるとします。

ダウンロードする生の結果: "Esdrújulaprendañame-güena.jpg" [醜い]

ダウンロードするHtmlEncodeの結果: "Esdr&_250; jula prenda&_241; ame-g&_252; ena.jpg" [醜い]

ダウンロードするUrlEncode結果: " Esdrújula+ prenda +ñame+-+güena.jpg " [OK]

次に、ほとんどの場合、ファイル名に対してUrlEncodeを使用する必要があります。さらに、content-dispositionヘッダーを直接文字列として設定する場合は、ブラウザーの互換性の問題を回避するために、引用符で囲む必要があります。

Response.AddHeader("Content-Disposition", $"attachment; filename=\"{HttpUtility.UrlEncode(YourFilename)}\"");

またはクラスエイドと:

var cd = new ContentDisposition("attachment") { FileName = HttpUtility.UrlEncode(resultFileName) };
Response.AddHeader("Content-Disposition", cd.ToString());

System.Net.Mime。ContentDispositionクラスは引用符を処理します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.