无法从MVC Controller下载文件与Web Api下载文件对话

时间:2015-11-29 23:52:52

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

我有一个Asp.Net WebApi和一个Asp.Net MVC Web项目。 Web Api提供文件下载功能。浏览器请求MVC WebClient中的DownloadController,它与Web Api文件下载控制器进行通信。

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

浏览器获得了一个Download Pdf,它表示正在加载,但从未完成。

我保持内存流开放,直到文件下载在Web Api中完成。否则,我从Web Api到Web服务器得到一个null响应。

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

这是代码,

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; }
 }

1 个答案:

答案 0 :(得分:0)

好吧,我做了一些关于流的实验,并找到了一个简单的解决方案。 解决方案:

只需将字节数组从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");
            }
        }

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