【发布时间】: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