如何使用Web API返回文件?

时间:2012-06-20 18:07:40

标签: c# asp.net-web-api

我正在使用 ASP.NET Web API
我想从API(API生成)下载带有C#的PDF。

我可以让API返回byte[]吗?对于C#应用程序,我可以这样做:

byte[] pdf = client.DownloadData("urlToAPI");? 

File.WriteAllBytes()?

6 个答案:

答案 0 :(得分:140)

最好在其内部使用StreamContent返回HttpResponseMessage。

以下是示例:

public HttpResponseMessage GetFile(string id)
{
    if (String.IsNullOrEmpty(id))
        return Request.CreateResponse(HttpStatusCode.BadRequest);

    string fileName;
    string localFilePath;
    int fileSize;

    localFilePath = getFileFromID(id, out fileName, out fileSize);

    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
    response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    response.Content.Headers.ContentDisposition.FileName = fileName;
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

    return response;
}
来自patridge的评论

UPD : 如果其他人到这里寻找从字节数组而不是实际文件发出响应,那么您将需要使用新的ByteArrayContent(someData)而不是StreamContent(请参阅here)。

答案 1 :(得分:32)

我做了以下行动:

[HttpGet]
[Route("api/DownloadPdfFile/{id}")]
public HttpResponseMessage DownloadPdfFile(long id)
{
    HttpResponseMessage result = null;
    try
    {
        SQL.File file = db.Files.Where(b => b.ID == id).SingleOrDefault();

        if (file == null)
        {
            result = Request.CreateResponse(HttpStatusCode.Gone);
        }
        else
        {
            // sendo file to client
            byte[] bytes = Convert.FromBase64String(file.pdfBase64);


            result = Request.CreateResponse(HttpStatusCode.OK);
            result.Content = new ByteArrayContent(bytes);
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            result.Content.Headers.ContentDisposition.FileName = file.name + ".pdf";
        }

        return result;
    }
    catch (Exception ex)
    {
        return Request.CreateResponse(HttpStatusCode.Gone);
    }
}

答案 2 :(得分:5)

IHttpActionResult中的ApiController示例。

[HttpGet]
[Route("file/{id}/")]
public IHttpActionResult GetFileForCustomer(int id)
{
    if (id == 0)
      return BadRequest();

    var file = GetFile(id);

    IHttpActionResult response;
    HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK);
    responseMsg.Content = new ByteArrayContent(file.SomeData);
    responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName;
    responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    response = ResponseMessage(responseMsg);
    return response;
}

如果您不想下载PDF并使用PDF查看器内置的浏览器,请删除以下两行:

responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName;

答案 3 :(得分:2)

我一直在想是否有一种简单的方法可以以一种更“通用”的方式下载文件。我想到了这个。

这是一个简单的ActionResult,可让您从返回IHttpActionResult的控制器调用中下载文件。 该文件存储在byte[] Content中。您可以根据需要将其转换为流。

我用它来返回存储在数据库的varbinary列中的文件。

    public class FileHttpActionResult : IHttpActionResult
    {
        public HttpRequestMessage Request { get; set; }

        public string FileName { get; set; }
        public string MediaType { get; set; }
        public HttpStatusCode StatusCode { get; set; }

        public byte[] Content { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = new HttpResponseMessage(StatusCode);

            response.StatusCode = StatusCode;
            response.Content = new StreamContent(new MemoryStream(Content));
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = FileName;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaType);

            return Task.FromResult(response);
        }
    }

答案 4 :(得分:1)

只是.Net Core的注释:如果要发送原始字节,可以使用FileContentResult并将contentType设置为application/octet-stream。示例:

[HttpGet("{id}")]
public IActionResult GetDocumentBytes(int id)
{
    byte[] byteArray = GetDocumentByteArray(id);
    return new FileContentResult(byteArray, "application/octet-stream");
}

答案 5 :(得分:0)

下载文件的另一种方法是将流内容直接写入响应的正文:

[HttpGet("pdfstream/{id}")]
public async Task  GetFile(long id)
{        
    var stream = GetStream(id);
    Response.StatusCode = (int)HttpStatusCode.OK;
    Response.Headers.Add( HeaderNames.ContentDisposition, $"attachment; filename=\"{Guid.NewGuid()}.pdf\"" );
    Response.Headers.Add( HeaderNames.ContentType, "application/pdf"  );            
    await stream.CopyToAsync(Response.Body);
    await Response.Body.FlushAsync();           
}