【问题标题】:Download Binary from WebApi2 As File. Server Side从 WebApi2 下载二进制文件作为文件。服务器端
【发布时间】:2015-08-04 16:55:30
【问题描述】:

我在这里查看了几个答案,但仍有问题。
一个系统正在使用 Entity Framework 6 将二进制字节 [] 保存到 SQL 2014 中。

我有一个记录的“名称”(不是文件),但我想通过 webapi2 将二进制数据作为可下载文件提供。我让它有点工作,但在浏览器上它显示 ID 作为文件名并说无法下载文件。它正在提示下载,但它不能。

现在对于 PoC,我正在将 mime 类型硬编码为 word docs。我做错了什么,我应该如何重构它以提供文件名。

我正在使用 Office 应用程序的任务窗格保存文档:

https://msdn.microsoft.com/en-us/library/office/jj715284.aspx

FileType: "Compressed" = 以字节数组的形式返回 Office Open XML (OOXML) 格式的整个文档(.pptx 或 .docx)。

Office.context.document.getSelectedDataAsync(Office.CoercionType.Text,
            function (result) {
                if (result.status === Office.AsyncResultStatus.Succeeded) {
                    vm.data.data = result.value;
                    //I call a angularJs service which post..
                   //return $http.post('https://stapi.local:8443/api/activities', vm.data);

                } else {

                }
            }
        );

然后我尝试让用户使用以下内容下载文档。

WebAPI2 控制器:

[HttpGet, Route("api/activityObjectFile/{id}/{name}")]
        public HttpResponseMessage GetDataFile(int id)
        {
            var fileByte = _activityService.GetFile(id);
            HttpResponseMessage response = new HttpResponseMessage { Content = new StreamContent(new MemoryStream(fileByte))};
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/msword");
            response.Content.Headers.ContentLength = fileByte.Length;
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment filename=test.docx");

            return response;
        }

类服务库:

public Byte[] GetFile(int id)
        {
            var existingActivityObjectFile = _repo.QueryAll<ActivityObject>().Where(a => a.Id == id).Select(a => a.BinaryData).First();

            return existingActivityObjectFile;
        }

客户端网址:

<a href="http://stapi.local/api/activityObjectFile/14">Download</a>

【问题讨论】:

  • 使用上述客户端 URL,文件将始终使用您的最终 URL 段的名称。出于测试目的,您可以尝试在/activityObjectFile/14 之后添加任意文件名,例如:activityObjectFile/14/test.docx。您的 WebAPI2 控制器似乎已将路由设置为接受文件名作为路由的一部分,但您似乎并未使用它。

标签: c# asp.net entity-framework-6 asp.net-web-api2 binaryfiles


【解决方案1】:

这应该让你现在开始:

var response = new HttpResponseMessage(HttpStatusCode.OK) 
{ 
   Content = new StreamContent(new MemoryStream(fileByte))        
};
response.Content
        .Headers
        .Add("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") 
{ 
   FileName = "test.docx" 
};
return response;

关于重构的建议,可以使用我的方法。

我有一个我返回的IHttpActionResult 的实现,它看起来像这样:

public class DocumentAttachmentResult : IHttpActionResult {
    private readonly string fileName;
    private readonly string mimeType;
    private readonly byte[] blob;

    public DocumentAttachmentResult(string fileName, string mimeType, byte[] blob) {
        this.fileName = fileName;
        this.mimeType = mimeType;
        this.blob = blob;
    }

    private HttpResponseMessage Execute() {
        var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(new MemoryStream(this.blob)) };
        response.Content.Headers.Add("Content-Type", this.mimeType);
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = this.fileName };
        return response;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) {
        return Task.FromResult(this.Execute());
    }
}

我的控制器操作如下所示:

    [HttpGet]
    [Route("attachments/{id:guid}/download")]
    public IHttpActionResult DownloadAttachment(Guid id) {
        var attachment = this.repository.FindById(id);
        if (attachment == null) {
            return this.NotFound();
        }
        return new DocumentAttachmentResult(attachment.Name, attachment.FileType.MimeType, attachment.BinaryBlob);
    }

我将文件名、mime 类型和二进制文件存储在 SQL Server 中,并将其建模为一个名为 Attachment 的实体。当我在 WebApi 控制器上使用另一个操作上传文件时,会捕获 mime 类型和文件。

【讨论】:

  • 我试过了,我似乎有同样的问题。浏览器要保存文件“14”,这是我发送的 ID,当我尝试在 IE 下载管理器中保存时,它显示“无法下载此文件。”
  • @Mastro 你用的是什么版本的IE?同样在您的内容处置标题中,您在附件后缺少一个分号,它应该是attachment; filename=test.docx
  • 在这台机器上,它在 Microsoft Edge (Windows 10) 机器上弹出。让我去试试我的 Windows 8 (IE) 机器。
  • 好的,在我的另一台机器上试了一下,IE 崩溃了。也许这与我保存它的方式有关。我正在使用msdn.microsoft.com/en-us/library/office/jj715284.aspx 从 Word 中保存二进制数据。文件类型“压缩”。我假设它是您拥有的 Open XML minetype。
  • 我现在正在使用 Anish Patel 的代码。但是同样的问题,认为它可能与 byte[] 数据有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-11
  • 2018-02-19
  • 1970-01-01
相关资源
最近更新 更多