You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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,但如果是其他类型的流,需要注意资源释放逻辑。

额外注意事项

  1. 权限配置:确保应用程序池的身份对PDF存储文件夹有读取权限,否则会出现权限不足的错误。
  2. 大文件优化:如果要下载大体积PDF,建议使用FileStream代替File.ReadAllBytes,避免一次性将整个文件加载到内存中,导致内存占用过高。
  3. 异常处理:可以在Action中添加try-catch块,捕获文件读取、路径处理等过程中的异常,返回更详细的错误信息。

内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:22:58