5

我有一个Web API控制器,它看起来像这样:如何使用ASP.net Web API和Javascript下载二进制文件?

using System; 
using System.Net; 
using System.Net.Http; 
using System.Net.Http.Headers; 
using System.Web.Http; 
using System.Threading.Tasks; 
using System.IO; 

    namespace APIIntegration.Controllers 
    { 
     public class TestController : ApiController 
     { 
      // http://localhost/api/test 
      [HttpGet]   
      public async Task<HttpResponseMessage> Get() 
      { 
       Stream stream = streamWith256Bytes;    
       HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);    
       result.Content = new StreamContent(stream); 
       result.Content.Headers.ContentLength = stream.Length;    
       result.Content.Headers.ContentType = 
        new MediaTypeHeaderValue("application/octet-stream"); 
       result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); 
       result.Content.Headers.ContentDisposition.FileName = "foo.bin"; 
       return result; 
      } 

      private static Stream streamWith256Bytes 
      { 
       get 
       { 
        MemoryStream stream = new MemoryStream(); 
        for (int i = 0; i <256 ; i++) 
        { 
         stream.WriteByte(Convert.ToByte(i)); 
        } 
        stream.Position = 0; 
        return stream; 
       } 
      } 
     } 
    } 

总之,该控制器会尝试一个256字节的文件下载到浏览器。起初,它似乎工作,但是当检查下载的文件时,大小是512字节而不是预期的256字节,并且不可打印的字符被丢弃。

如何修改此代码以便可以正确下载二进制数据?

编辑:我还要提到的是我看到了类似的问题在这里:Problems with downloading pdf file from web api service其中问题得到了解决通过添加Content-Length头,但是这并没有解决这个问题对我来说。

编辑:我修改了上面的源代码,给出了一个完整的,如何重现的工作示例。

编辑:我发现上面的代码实际上正确地工作,当我在地址栏中键入地址,但是当使用JavaScript来启动下载时,这就是我遇到问题的地方。

+0

我认为这可能是MemoryStream的是如何工作的细微差别。尝试填充正常的Byte []并用它构造MemoryStream,而不是直接写入空实例。 – Machinarius

回答

4

我找到了解决办法。在我的Javascript中,我使用Angular来使用Angular $ http服务启动文件下载。默认情况下,此服务将响应解释为文本。我不得不告诉Angular将响应解释为一个blob,并且解决了所有问题。

我工作的代码如下所示:

function download(downloadUrl) { 
    $http({ 
     url: downloadUrl, 
     responseType: "blob" 
    }) 
    .then(function (response) { 
     var blob = new Blob([response.data], { type: "application/octet-stream" }); 
     saveAs(blob, "foo.bin"); 
    }, function (response) { 
     alert("error downloading file from " + downloadUrl); 
    }); 
} 
+0

responseType:“blob”!!!! – Pascal

相关问题