developer tip

이름이있는 브라우저에서 ASP.NET MVC FileContentResult를 사용하여 파일을 스트리밍 하시겠습니까?

copycodes 2020. 12. 10. 20:42
반응형

이름이있는 브라우저에서 ASP.NET MVC FileContentResult를 사용하여 파일을 스트리밍 하시겠습니까?


특정 이름의 브라우저 내에서 ASP.NET MVC FileContentResult를 사용하여 파일을 스트리밍하는 방법이 있습니까?

FileDialog (열기 / 저장)를 사용하거나 브라우저 창에서 파일을 스트리밍 할 수 있지만 파일을 저장하려고 할 때 ActionName을 사용합니다.

다음과 같은 시나리오가 있습니다.

byte[] contents = DocumentServiceInstance.CreateDocument(orderId, EPrintTypes.Quote);
result = File(contents, "application/pdf", String.Format("Quote{0}.pdf", orderId));

이것을 사용하면 바이트를 스트리밍 할 수 있지만 OPEN / SAVE 파일 대화 상자가 사용자에게 제공됩니다. 실제로이 파일을 브라우저 창에서 스트리밍하고 싶습니다.

FilePathResult 만 사용하면 브라우저 창에 파일이 표시되지만 "저장"버튼을 클릭하여 파일을 PDF로 저장하면 파일 이름으로 Action Name이 표시됩니다.

누구든지 이것을 만났습니까?


public ActionResult Index()
{
    byte[] contents = FetchPdfBytes();
    return File(contents, "application/pdf", "test.pdf");
}

브라우저에서 PDF를 열려면 Content-Disposition헤더 를 설정해야합니다 .

public ActionResult Index()
{
    byte[] contents = FetchPdfBytes();
    Response.AddHeader("Content-Disposition", "inline; filename=test.pdf");
    return File(contents, "application/pdf");
}

실제로 가장 쉬운 방법은 다음을 수행하는 것입니다.

byte[] content = your_byte[];

FileContentResult result = new FileContentResult(content, "application/octet-stream") 
                 {
                     FileDownloadName = "your_file_name"
                 };

return result;

이 문제에 직면 한 다른 사람에게 도움이 될 수 있습니다. 마침내 해결책을 찾았습니다. "content-disposition"에 인라인을 사용하고 파일 이름을 지정하더라도 브라우저는 여전히 파일 이름을 사용하지 않습니다. 대신 브라우저는 경로 / URL을 기반으로 파일 이름을 해석합니다.

이 URL에서 더 자세히 읽을 수 있습니다. 올바른 파일 이름으로 브라우저 내에서 안전하게 파일 다운로드

이것은 나에게 아이디어를 주었다. 방금 URL을 변환하고 파일에 제공하려는 파일의 이름으로 끝낼 URL 경로를 만들었습니다. 예를 들어 내 원래 컨트롤러 호출은 인쇄되는 주문의 주문 ID를 전달하는 것으로 구성되었습니다. 파일 이름이 Order {0} .pdf 형식이 될 것으로 예상했습니다. 여기서 {0}는 주문 ID입니다. 따옴표도 마찬가지로 Quote {0} .pdf를 원했습니다.

컨트롤러에서 파일 이름을 받아들이는 추가 매개 변수를 추가했습니다. URL.Action 메서드에서 파일 이름을 매개 변수로 전달했습니다.

그런 다음 해당 URL을 http : //localhost/ShoppingCart/PrintQuote/1054/Quote1054.pdf 형식으로 매핑하는 새 경로를 만들었습니다 .


routes.MapRoute("", "{controller}/{action}/{orderId}/{fileName}",
                new { controller = "ShoppingCart", action = "PrintQuote" }
                , new string[] { "x.x.x.Controllers" }
            );

이것은 내 문제를 거의 해결했습니다. 이것이 누군가에게 도움이되기를 바랍니다!

치어 즈, 아눕


이전 답변이 맞습니다 : 줄 추가 ...

Response.AddHeader("Content-Disposition", "inline; filename=[filename]");

... 여러 Content-Disposition 헤더가 브라우저로 전송됩니다. 이것은 FileContentResult파일 이름을 제공하면 내부적으로 헤더를 적용하는 b / c가 발생 합니다. 대안이며 매우 간단한 해결책은 단순히 하위 클래스를 만들고 메서드를 FileContentResult재정의하는 ExecuteResult()것입니다. 다음은 System.Net.Mime.ContentDisposition클래스 의 인스턴스 (내부 FileContentResult구현에 사용 된 동일한 개체) 를 인스턴스화 하고 새 클래스에 전달 하는 예제입니다 .

public class FileContentResultWithContentDisposition : FileContentResult
{
    private const string ContentDispositionHeaderName = "Content-Disposition";

    public FileContentResultWithContentDisposition(byte[] fileContents, string contentType, ContentDisposition contentDisposition)
        : base(fileContents, contentType)
    {
        // check for null or invalid ctor arguments
        ContentDisposition = contentDisposition;
    }

    public ContentDisposition ContentDisposition { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        // check for null or invalid method argument
        ContentDisposition.FileName = ContentDisposition.FileName ?? FileDownloadName;
        var response = context.HttpContext.Response;
        response.ContentType = ContentType;
        response.AddHeader(ContentDispositionHeaderName, ContentDisposition.ToString());
        WriteFile(response);
    }
}

당신의에서 Controller, 또는베이스 Controller, 당신은을 인스턴스화하는 간단한 도우미 쓸 수 있습니다 FileContentResultWithContentDisposition다음과 같이 당신의 액션 메소드에서 호출을 :

protected virtual FileContentResult File(byte[] fileContents, string contentType, ContentDisposition contentDisposition)
{
    var result = new FileContentResultWithContentDisposition(fileContents, contentType, contentDisposition);
    return result;
}

public ActionResult Report()
{
    // get a reference to your document or file
    // in this example the report exposes properties for
    // the byte[] data and content-type of the document
    var report = ...
    return File(report.Data, report.ContentType, new ContentDisposition {
        Inline = true,
        FileName = report.FileName
    });
}

이제 선택한 파일 이름과 "inline; filename = [filename]"의 내용 처리 헤더를 사용하여 파일이 브라우저로 전송됩니다.

도움이 되었기를 바랍니다.


The absolute easiest way to stream a file into browser using ASP.NET MVC is this:

public ActionResult DownloadFile() {
    return File(@"c:\path\to\somefile.pdf", "application/pdf", "Your Filename.pdf");
}

This is easier than the method suggested by @azarc3 since you don't even need to read the bytes.

Credit goes to: http://prideparrot.com/blog/archive/2012/8/uploading_and_returning_files#how_to_return_a_file_as_response

** Edit **

Apparently my 'answer' is the same as the OP's question. But I am not facing the problem he is having. Probably this was an issue with older version of ASP.NET MVC?


public FileContentResult GetImage(int productId) { 
     Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId); 
     if (prod != null) { 
         return File(prod.ImageData, prod.ImageMimeType); 
      } else { 
         return null; 
     } 
}

참고URL : https://stackoverflow.com/questions/3206682/stream-file-using-asp-net-mvc-filecontentresult-in-a-browser-with-a-name

반응형