programing

ASP에서 파일(FileContentResult)을 반환하는 방법.NET 웹 API

cafebook 2023. 4. 28. 21:31
반응형

ASP에서 파일(FileContentResult)을 반환하는 방법.NET 웹 API

일반 MVC 컨트롤러에서, 우리는 pdf를 출력할 수 있습니다.FileContentResult.

public FileContentResult Test(TestViewModel vm)
{
    var stream = new MemoryStream();
    //... add content to the stream.

    return File(stream.GetBuffer(), "application/pdf", "test.pdf");
}

하지만 어떻게 우리가 그것을 변화시킬 수 있습니까?ApiController?

[HttpPost]
public IHttpActionResult Test(TestViewModel vm)
{
     //...
     return Ok(pdfOutput);
}

여기 제가 시도한 것이 있는데 작동이 안 되는 것 같습니다.

[HttpGet]
public IHttpActionResult Test()
{
    var stream = new MemoryStream();
    //...
    var content = new StreamContent(stream);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    content.Headers.ContentLength = stream.GetBuffer().Length;
    return Ok(content);            
}

브라우저에 표시되는 결과는 다음과 같습니다.

{"Headers":[{"Key":"Content-Type","Value":["application/pdf"]},{"Key":"Content-Length","Value":["152844"]}]}

그리고 SO에도 비슷한 게시물이 있습니다: ASP의 컨트롤러에서 바이너리 파일을 반환하는 것.NET Web API. 기존 파일의 출력에 대해 설명합니다.하지만 저는 그것을 개울에서 작동시킬 수 없었습니다.

좋은 의견이라도 있나?

돌아오는 대신에StreamContent처럼Content저는 그것을 작동시킬 수 있습니다.ByteArrayContent.

[HttpGet]
public HttpResponseMessage Generate()
{
    var stream = new MemoryStream();
    // processing the stream.

    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(stream.ToArray())
    };
    result.Content.Headers.ContentDisposition =
        new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
    {
        FileName = "CertificationCard.pdf"
    };
    result.Content.Headers.ContentType =
        new MediaTypeHeaderValue("application/octet-stream");

    return result;
}

반품을 원하신다면IHttpActionResult다음과 같이 할 수 있습니다.

[HttpGet]
public IHttpActionResult Test()
{
    var stream = new MemoryStream();

    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(stream.GetBuffer())
    };
    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
    {
        FileName = "test.pdf"
    };
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    var response = ResponseMessage(result);

    return response;
}

질문은 저에게 도움이 되었습니다.

다음을 시도해 보십시오.

컨트롤러 코드:

[HttpGet]
public HttpResponseMessage Test()
{
    var path = System.Web.HttpContext.Current.Server.MapPath("~/Content/test.docx");;
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = new FileStream(path, FileMode.Open);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    result.Content.Headers.ContentDisposition.FileName = Path.GetFileName(path);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    result.Content.Headers.ContentLength = stream.Length;
    return result;          
}

HTML 마크업 보기(클릭 이벤트 및 단순 URL 포함):

<script type="text/javascript">
    $(document).ready(function () {
        $("#btn").click(function () {
            // httproute = "" - using this to construct proper web api links.
            window.location.href = "@Url.Action("GetFile", "Data", new { httproute = "" })";
        });
    });
</script>


<button id="btn">
    Button text
</button>

<a href=" @Url.Action("GetFile", "Data", new { httproute = "" }) ">Data</a>

파일의 내용을 버퍼링하지 않고 스트리밍하는 구현체가 있습니다(바이트[] / MemoryStream 등의 버퍼링은 큰 파일일 경우 서버 문제가 될 수 있습니다).

public class FileResult : IHttpActionResult
{
    public FileResult(string filePath)
    {
        if (filePath == null)
            throw new ArgumentNullException(nameof(filePath));

        FilePath = filePath;
    }

    public string FilePath { get; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.OK);
        response.Content = new StreamContent(File.OpenRead(FilePath));
        var contentType = MimeMapping.GetMimeMapping(Path.GetExtension(FilePath));
        response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
        return Task.FromResult(response);
    }
}

다음과 같이 간단히 사용할 수 있습니다.

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        string filePath = GetSomeValidFilePath();
        return new FileResult(filePath);
    }
}

정확히 어느 부분을 탓해야 할지는 모르겠지만, 여기 이유가 있습니다.MemoryStream사용자에게 적합하지 않습니다.

편지를 쓰는 대로MemoryStream그것은 그것을 증가시킵니다.Position소유물.의 생성자StreamContent스트림의 전류를 고려합니다.Position그래서 만약 당신이 스트림에 글을 쓴다면, 그것을 전달하세요.StreamContent응답은 스트림 끝에 있는 무에서 시작됩니다.

이 문제를 올바르게 해결하는 두 가지 방법이 있습니다.

  1. 내용 구성, 스트림에 쓰기

     [HttpGet]
     public HttpResponseMessage Test()
     {
         var stream = new MemoryStream();
         var response = Request.CreateResponse(HttpStatusCode.OK);
         response.Content = new StreamContent(stream);
         // ...
         // stream.Write(...);
         // ...
         return response;
     }
    
  2. 스트림에 쓰기, 위치 재설정, 내용 구성

     [HttpGet]
     public HttpResponseMessage Test()
     {
         var stream = new MemoryStream();
         // ...
         // stream.Write(...);
         // ...
         stream.Position = 0;
    
         var response = Request.CreateResponse(HttpStatusCode.OK);
         response.Content = new StreamContent(stream);
         return response;
     }
    
  3. 신선한 스트림이 있으면 조금 더 좋아 보입니다. 1) 스트림이 0에서 시작하지 않으면 더 단순합니다.

나에게 그것은 사이의 차이였습니다.

var response = Request.CreateResponse(HttpStatusCode.OK, new StringContent(log, System.Text.Encoding.UTF8, "application/octet-stream");

그리고.

var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(log, System.Text.Encoding.UTF8, "application/octet-stream");

첫 번째는 문자열 내용: {"Headers": [{"Key": "Content-Type", "Value":의 JSON 표현을 반환하는 것이었습니다.["애플리케이션/옥텟 스트림; charset=utf-8"]}}

두 번째 파일이 제대로 반환되는 동안.

요청하신 것 같습니다.CreateResponse에는 문자열을 두 번째 매개 변수로 사용하는 오버로드가 있으며 이로 인해 StringContent 개체 자체가 실제 내용이 아닌 문자열로 렌더링된 것으로 보입니다.

저는 이 기사가 유용하다고 생각했습니다: https://codeburst.io/download-files-using-web-api-ae1d1025f0a9

기본적으로 다음과 같습니다.

[Route("api/[controller]")]
[ApiController]
public class JobController : ControllerBase
{
    [HttpGet]
    public ActionResult GetFile()
    {
        byte[] fileContent = GetFile();
        return File(fileContent, "application/pdf", "test.pdf");
    }
}
 var memoryStream = new MemoryStream();
                await cloudFile.DownloadToStreamAsync(memoryStream);
                responseMessage.result = "Success";

                var contentType = "application/octet-stream";
            
                **using (var stream = new MemoryStream())
                {                    
                    return File(memoryStream.GetBuffer(), contentType, "Cartage.pdf");
                }**

언급URL : https://stackoverflow.com/questions/26038856/how-to-return-a-file-filecontentresult-in-asp-net-webapi

반응형