【问题标题】:Convert HttpResponseBase to IHttpActionResult将 HttpResponseBase 转换为 IHttpActionResult
【发布时间】:2018-06-05 04:48:00
【问题描述】:

如何在IHttpActionResult action, Web API controller中实现如下功能?

我需要将HttpResponseBase 修改为其他内容吗?

public void ZipFilesToResponse(HttpResponseBase response, IEnumerable<Asset> files, string zipFileName)
{
    using (var zipOutputStream = new ZipOutputStream(response.OutputStream))
    {
        zipOutputStream.SetLevel(0); // 0 - store only to 9 - means best compression
        response.BufferOutput = false;
        response.AddHeader("Content-Disposition", "attachment; filename=" + zipFileName);
        response.ContentType = "application/octet-stream";

        foreach (var file in files)
        {
            var entry = new ZipEntry(file.FilenameSlug())
            {
                DateTime = DateTime.Now,
                Size = file.Filesize
            };
            zipOutputStream.PutNextEntry(entry);
            storageService.ReadToStream(file, zipOutputStream);
            response.Flush();
            if (!response.IsClientConnected)
            {
               break;
            }
        }
        zipOutputStream.Finish();
        zipOutputStream.Close();
    }
    response.End();
}

在这里使用:

[HttpPost]
[Route("DownloadFiles/{company_id}")]
public IHttpActionResult DownloadFiles(Int64 company_id, TasksFilterModel searchModel)
{
     var files = .....;
     ZipFilesToResponse(_______,files,"download.zip");
     return ????
}

【问题讨论】:

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


【解决方案1】:

您当前的 ZipFilesToResponse 方法更多地是为常规 MVC 而构建的,而不是 Web API。一种选择是简单地将这个动作移动到 MVC 控制器而不是 Web API 控制器中。

public class MyController : Controller
{
    [HttpPost]
    [Route("DownloadFiles/{company_id}")]
    public void DownloadFiles(Int64 company_id, TasksFilterModel searchModel)
    {
         var files = ...;
         ZipFilesToResponse(HttpContext.Response, files, "download.zip");
    }
}

您不需要返回任何内容,因为您的 ZipFilesToResponse 方法直接写入 HttpContext.Response 对象。

或者,如果您想坚持使用纯 Web API,我们可以修改 ZipFilesToResponse 方法以创建 HttpResponseMessage,然后从您的操作中返回它。

[Route("DownloadFiles")]
[HttpGet]
public HttpResponseMessage DownloadFiles()
{
    var files = ...;
    return ZipContentResult(files, "download.zip");
}

protected HttpResponseMessage ZipContentResult(IEnumerable<Asset> files, string zipFileName)
{
    var pushStreamContent = new PushStreamContent((stream, content, context) =>
    {
        using (var zipOutputStream = new ZipOutputStream(stream))
        {
            zipOutputStream.SetLevel(0); // 0 - store only to 9 - means best compression

            foreach (var file in files)
            {
                var entry = new ZipEntry(file.FilenameSlug())
                {
                    DateTime = DateTime.Now,
                    Size = file.Filesize
                };
                zipOutputStream.PutNextEntry(entry);
                storageService.ReadToStream(file, zipOutputStream);
                stream.Flush();
             }
             zipOutputStream.Finish();
             zipOutputStream.Close();
        }
        stream.Close();
    }, "application/zip");

    pushStreamContent.Headers.Add("Content-Disposition", "attachment; filename=" + zipFileName);

    return new HttpResponseMessage(HttpStatusCode.OK) { Content = pushStreamContent };
}

【讨论】:

  • 另外,要使用您的代码在 DownloadFiles 中返回 IHttpActionResult,可以编写 return ResponseMessage(ZipContentResult(files));。虽然它并没有真正带来任何额外的好处。
  • 在前端下载不会自动开始。我错过了什么吗?
  • @ShyamalParikh 当您到达端点 (/DownloadFiles/...) 时会发生什么?是否返回任何错误?我意识到在我的第二个示例中我使用了 [HttpGet] 而不是 [HttpPost],请确保更改它以满足您的要求。
  • 客户端收到文件但下载模式未触发以将文件保存在客户端
  • 好的,正在触发下载,但是打开 zip 文件时出错
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多