如何在Controller中从文件夹下载PDF?附C#实现代码
在ASP.NET Web API控制器中实现PDF文件下载
针对你提出的“如何在控制器中从文件夹下载PDF”的需求,我结合你提供的代码片段,整理出完整且可运行的实现方案,同时补充关键细节和注意事项:
完整实现代码
首先是控制器中的下载Action,以及对应的自定义IHttpActionResult实现类:
using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web; using System.Web.Http; using System.Configuration; public class PdfDownloadController : ApiController { [Route("pdfdownload")] [HttpGet] public IHttpActionResult GetPdfDownload(string parameter) { // 基础校验:避免空参数导致路径错误 if (string.IsNullOrEmpty(parameter)) { return BadRequest("PDF文件名参数不能为空"); } // 从配置文件获取PDF存储根路径 string rootPath = ConfigurationManager.AppSettings["SISource"]?.ToString(); if (string.IsNullOrEmpty(rootPath)) { return InternalServerError(new Exception("未配置PDF存储路径")); } // 拼接完整文件路径(这里建议做路径安全校验,防止目录遍历攻击) string pdfFilePath = Path.Combine(rootPath, parameter); // 检查文件是否存在 if (!File.Exists(pdfFilePath)) { return NotFound(); } // 读取文件字节流 byte[] pdfBytes = File.ReadAllBytes(pdfFilePath); MemoryStream pdfStream = new MemoryStream(pdfBytes); // 返回自定义的下载结果 return new GetPDFDownload(pdfStream, Request, parameter); } } public class GetPDFDownload : IHttpActionResult { private readonly MemoryStream _pdfStream; private readonly HttpRequestMessage _request; private readonly string _fileName; // 构造函数注入所需资源 public GetPDFDownload(MemoryStream pdfStream, HttpRequestMessage request, string fileName) { _pdfStream = pdfStream; _request = request; _fileName = fileName; } // 实现IHttpActionResult的核心方法 public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(_pdfStream) }; // 设置响应头,指定文件类型和下载方式 response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf"); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = _fileName }; // 关联请求和响应 response.RequestMessage = _request; return Task.FromResult(response); } }
关键细节解释
- 路由与请求方式:
[Route("pdfdownload")]定义了访问该接口的路径,[HttpGet]指定这是一个GET请求,前端可以通过/pdfdownload?parameter=xxx.pdf的方式调用。 - 路径安全处理:使用
Path.Combine拼接路径比直接用+ "\\"更安全,同时要对传入的parameter参数做校验(比如限制只能是合法文件名,禁止包含../这类目录遍历字符),防止恶意路径注入。 - 文件存在性校验:在读取文件前先检查文件是否存在,避免抛出文件未找到的异常,返回更友好的
NotFound()响应。 - 自定义IHttpActionResult:通过实现
IHttpActionResult可以更灵活地控制响应头和流的处理,设置ContentDisposition为attachment可以让浏览器触发下载行为,而不是直接打开PDF。 - 资源释放:
StreamContent会自动处理内存流的释放,无需手动调用Dispose,但如果是其他类型的流,需要注意资源释放逻辑。
额外注意事项
- 权限配置:确保应用程序池的身份对PDF存储文件夹有读取权限,否则会出现权限不足的错误。
- 大文件优化:如果要下载大体积PDF,建议使用
FileStream代替File.ReadAllBytes,避免一次性将整个文件加载到内存中,导致内存占用过高。 - 异常处理:可以在Action中添加
try-catch块,捕获文件读取、路径处理等过程中的异常,返回更详细的错误信息。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

