ASP.NET 웹 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-이것은 웹 API 컨트롤러 메소드입니다. 아마도 IIS로 들어오는 HTTP 요청을 통해 호출되고 구문 분석하고 메소드를 호출하는 경로와 웹 API를 찾는 것입니다 (물론 테스트에 의해 호출됩니다).
Dave Rael

GetMyForm () 안에서 무슨 일이 일어나고 있습니까? 파일을 바이트 스트림으로 변환합니까?
MSIslam

@MSIslam 종류의. 이 함수는 사용자 양식에서 정보를 가져와 결과 스트림으로 변환하기 전에 파일을 작성합니다.
태 성 신

답변:


289

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
"첨부 파일"처리 유형에 대해 궁금한 사람은 전체 처리 유형 목록은 iana.org/assignments/cont-disp/cont-disp.xhtml
sfuqua

1
여기에서 파일다운로드하는 것에 대한 또 다른 답변이 있습니다. 당신이 사용하는지 System.Net.Mime.ContentDisposition또는 중요합니까 ContentDispositionHeaderValue? 하나는 다른 것보다 더 최신이며 더 선호됩니까?
빛나는

@Luminous 하나의 대답은 ActionResult, 하나는HttpResponseMessage
weston

@west에서 귀하의 답변이 내 질문에 답변하지 않습니다.
Luminous

4
@Luminous "중요합니까?"및 "하나가 더 중요하고 다른 것보다 선호됩니까?" 아니, 아니 하나는 MVC 용 ActionResult이고 다른 하나는 WebApi 용 HttpResponseMessage입니다.
weston

27

편집 : 의견에서 언급했듯이, 내 대답은처럼 탈출 해야하는 문자를 설명하지 않습니다 ;. 파일 이름에 세미콜론이 포함될 수있는 경우 허용되는 Darin 답변을 사용해야합니다.

파일 이름을 설정하려면 Response.AddHeader를 추가하십시오.

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

FILE_NAME을 파일 이름으로 변경하십시오.


2
이것은 질문자와 비슷한 문제를 해결하는 데 도움이되었습니다. 필자의 경우 IE8에서 문제의 파일 형식을 항상 열 수있는 옵션을 제공하도록 "첨부 파일"을 "인라인"으로 변경하는 것이 유용하다는 것을 알았습니다.
Scott

2
탈출을 다루지 않습니다. 파일 이름 ;에 특별한 의미가있는 항목이 포함되어 있으면 어떻게 됩니까?
Sam

샘, 3 년 전이 답변을 썼을 때 탈출을 처리하는 데 필요한 답변을 몰랐습니다. 이것을 지적 해 주셔서 감사합니다. 나는 답변이 탈출을 설명하지 않는다고 설명하는 답변을 수정했습니다. 그러나 사람들에게 도움이 된 것 같아서 내 대답을 동일하게 유지하십시오.
KingPancake

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
탈출을 다루지 않습니다. 파일 이름 ;에 특별한 의미가있는 항목이 포함되어 있으면 어떻게 됩니까?
Sam

3

컨텐츠 처리 헤더를 응답에 추가해야합니다.

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

3
탈출을 다루지 않습니다. 파일 이름 ;에 특별한 의미가있는 항목이 포함되어 있으면 어떻게 됩니까?
Sam

3

ASP.NET Core MVC를 사용하는 경우 위의 답변은 약간 변경됩니다 ...

내 액션 메소드 (을 반환 async Task<JsonResult>)에서 라인을 반환합니다 (반환 문 앞의 아무 곳이나) :

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

탈출을 다루지 않습니다. 파일 이름에; 또는 특별한 의미가있는 다른 것?
KoalaBear

2

이것은해야합니다 :

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

2
탈출을 다루지 않습니다. 파일 이름 ;에 특별한 의미가있는 항목이 포함되어 있으면 어떻게 됩니까?
Sam

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újula prenda ñame-güena.jpg " 라고 가정하십시오.

원시 결과 다운로드 : "Esdrújula prenda à ± ame-güena.jpg"[Ugly]

HtmlEncode 다운로드 결과 : "Esdr & _250; Jula prenda & _241; ame-g & _252; ena.jpg"[Ugly]

UrlEncode 다운로드 결과 : " Esdrújula + prenda + ñame +-+ güena.jpg "[확인]

그런 다음 거의 항상 파일 이름 위에 UrlEncode를 사용해야합니다 . 또한 컨텐츠 처리 헤더를 직접 문자열로 설정 한 경우 브라우저 호환성 문제를 피하려면 따옴표묶어야 합니다.

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.