如何在.NET Framework 4.5环境中设计一个C#实现的Web API接口,用于高效地下载大文件?
时间: 2024-10-22 10:15:57 浏览: 6
在.NET Framework 4.5环境下,设计一个高效的Web API接口用于下载大文件,可以采用分块下载的方式,并考虑到并发处理以提高性能。以下是实现的一个简化示例:
```csharp
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace YourNamespace.Controllers
{
[ApiController]
[Route("api/file/download")]
public class FileDownloadController : ControllerBase
{
private readonly string _filePath; // 文件路径
public FileDownloadController(string filePath)
{
_filePath = filePath;
}
[HttpGet("{fileId}")]
public async Task<HttpResponseMessage> DownloadFile(long fileId)
{
if (!System.IO.File.Exists(_filePath))
{
return NotFound($"File with ID {fileId} not found.");
}
var fileStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
var totalSize = fileStream.Length;
var chunkSize = 4 * 1024 * 1024; // 4MB
var downloadTaskList = new List<Task>();
long currentOffset = 0;
while (currentOffset < totalSize)
{
downloadTaskList.Add(GetRangeDownload(fileStream, fileId, currentOffset, Math.Min(chunkSize, totalSize - currentOffset)));
currentOffset += chunkSize;
}
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new MultipartMemoryStreamProvider(); // 使用MultipartMemoryStreamProvider来支持分块传输
// 等待所有下载任务完成
await Task.WhenAll(downloadTaskList);
foreach (var task in downloadTaskList)
{
await task.Result.CopyToAsync(response.Content); // 将每个块写入响应
}
response.Content.Headers.ContentLength = totalSize;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = Path.GetFileNameWithoutExtension(_filePath)
};
return response;
}
private async Task<HttpResponseMessage> GetRangeDownload(Stream source, long fileId, long startOffset, long length)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new MemoryStream();
using (HttpContent content = new ByteArrayContent(new byte[length]))
{
content.Headers.ContentRange = new ContentRangeHeaderValue(startOffset, startOffset + length - 1, totalSize);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
// 开始下载并发送响应
using (FileStream stream = await source.CreateReadStreamAsync(startOffset, length))
{
await stream.CopyToAsync(content.ReadAsStreamAsync());
await content.CopyToAsync(response.Content);
}
}
response.Content.Headers.ContentLength = length;
return response;
}
}
}
```
这个示例中,我们使用`GetRangeDownload`方法异步地从源文件流中获取指定范围的字节,并将其放入`HttpResponseMessage`的内容中。通过这种方式,当文件非常大时,客户端可以逐个下载小块,而不是一次性加载整个文件。同时,通过`MultipartMemoryStreamProvider`,我们可以支持分块传输,以适应HTTP协议限制。
阅读全文