【问题标题】:Cannot download a file from MVC Controller talks to Web Api Download File无法从 MVC 控制器下载文件与 Web Api 下载文件对话
【发布时间】:2015-11-29 23:52:52
【问题描述】:

我有一个 Asp.Net WebApi 和一个 Asp.Net MVC Web 项目。 Web Api 提供文件下载功能。浏览器请求 MVC WebClient 中的 DownloadController 与 Web Api File 下载控制器对话。

我参考this文章实现文件下载到WebApi。(我尝试直接从浏览器调用Web api,如示例中所述,它有效)。但就我而言,我需要通过 MVC Web App 将文件发送到浏览器。 我将内存流获取到 Webserver(MVC 控制器),并在 WebServer 临时文件夹(C:\Temp 文件夹)中创建了一个文件,但大小为 0kb 并且无法打开(无法读取文件,某些进程是使用它)。重新启动 IIS 时,它会给出错误“格式异常:不是有效的 PDF 或已损坏”。

浏览器获取一个下载 PDF 并显示正在加载,但从未完成。

我将保持内存流打开,直到 Web Api 中的文件下载完成。否则,我会从 Web Api 到 Web 服务器得到空响应。

我在做一些不推荐的事情吗?处理这种情况的最佳方法是什么?

这是代码,

Web Api 工程,下载文件功能

 public HttpResponseMessage GetById(string fileid)
 {         
          //fileid = e.g. <someguid>.pdf
        try
        {                                
          var result = DownloadBlob(fileid);

          if (result == null)
          {
             return new HttpResponseMessage(HttpStatusCode.NotFound);
          }

         result.BlobStream.Position = 0;
         return Request.CreateResponse(HttpStatusCode.OK, result);

      }
   }

MVC Web App(与 Web Api 对话并需要发送文件响应)

public async Task<FileStreamResult> DownloadInvoice()
        {
            string id = "6bc7fb58-4bd3-4a09-bd90-98a837d4e441.pdf";

            //Call WebApiClient
            BcxApiConfiguration config = new BcxApiConfiguration();//This will load settings. These settings will be used in HMAC
            BcxBillingApi<BcxInvoiceFile> invoiceApi = new BcxBillingApi<BcxInvoiceFile>(config.Uri, config.AppId, config.ApiKey, organisationId);

            BcxInvoiceFile result = await invoiceApi.GetByIdAsync(id);

            //WRITE TO FILE
            string path = @"C:\Temp\" + result.BlobFileName;
            var fileStream = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite);

            fileStream.Position = 0;
            fileStream.CopyTo(result.BlobStream);

            return new FileStreamResult(fileStream, "application/pdf");

        }

在 Web Api 中下载 Helper,

public BcxInvoiceFile DownloadBlob(string blobFileId)
{
            var billingFileInstanceFileName = String.Empty;
            string destFile;
            // Retrieve storage account from connection string.
            var storageAccount = CloudStorageAccount.Parse(StorageAccountConnectionString);

            // Create the blob client.
            var blobClient = storageAccount.CreateCloudBlobClient();

            // Retrieve Storage container.
            var container = blobClient.GetContainerReference(StorageContainer);

            // Create the container if it doesn't already exist.
            container.CreateIfNotExists();


            // Retrieve Blob Reference.
            var blockBlob = container.GetBlockBlobReference(blobFileId);           

            string text;
            var memoryStream = new MemoryStream();
            blockBlob.DownloadToStream(memoryStream);
            text = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());

            // Strip off any folder structure so the file name is just the file name
            var lastPos = blockBlob.Name.LastIndexOf('/');
            var fileName = blockBlob.Name.Substring(lastPos + 1, blockBlob.Name.Length - lastPos - 1);

            // Build and return the download model with the blob stream and its relevant info
            var download = new BcxInvoiceFile
            {
                BlobStream = memoryStream,
                BlobFileName = fileName,
                BlobLength = blockBlob.Properties.Length,
                BlobContentType = blockBlob.Properties.ContentType
            };

            return download;

            // return billingFileInstanceFileName;
 }

文件下载的模型类,

 public class BcxInvoiceFile
 {
        public MemoryStream BlobStream { get; set; }
        public string BlobFileName { get; set; }
        public string BlobContentType { get; set; }
        public long BlobLength { get; set; }
 }

【问题讨论】:

  • 这行fileStream.CopyTo(result.BlobStream);不应该是await fileStream.CopyToAsync(result.BlobStream);
  • 试过了,没变。同样的问题。

标签: c# model-view-controller asp.net-web-api


【解决方案1】:

好吧,我对流进行了一些实验,并找到了一个让事情变得简单的解决方案。 解决方案:

只需将字节数组从 Web Api 传递到 MVC 控制器,然后从 MVC 控制器创建文件流。

来自 Web Api 控制器,

result.BlobStream.Position = 0;

return Request.CreateResponse(HttpStatusCode.OK, result.BlobStream.GetBuffer());

来自 MVC 控制器,(没有我正在使用的 Api 客户端的纯 c# 代码)

 public async Task<FileStreamResult> DownloadInvoice()
        {
            string invoiceId = new Guid(); //Test data
            var url = "http://localhost:7000/api/v1/downloadfile/<invoiceid goes here>";

            string path = @"C:\Temp\" + invoiceId + ".pdf";

            using (var client = new HttpClient())
            {
                var response = client.GetAsync(url).Result;

                var stream = await response.Content.ReadAsAsync<Byte[]>();

                System.IO.File.WriteAllBytes(path, stream);

                var fileStream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);

                return new FileStreamResult(fileStream, "application/pdf");
            }
        }

如果有人遇到更好的方法,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 2016-05-29
    • 1970-01-01
    • 2015-10-31
    • 2010-10-18
    相关资源
    最近更新 更多