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

.NET Core 6 API:扩展名未知时如何读取(GET)文件

问题解决与代码优化建议

一、让GET方法支持任意上传文件类型的方案

当前GET方法硬编码了.pdf后缀,要实现支持所有上传类型的文件下载,核心是找到对应requestId+lineNumber的文件实际扩展名,再动态读取文件并设置正确的Content-Type。

实现思路

  1. 生成文件基础名称(requestId与lineNumber拼接)
  2. 遍历支持的扩展名,检查哪个文件实际存在
  3. 找到目标文件后,根据扩展名匹配对应MIME类型,返回文件流

修改后的Download方法

[HttpGet("Download/{requestId}/{lineNumber}")]
public IActionResult Download([FromRoute] long requestId, [FromRoute] int lineNumber)
{
    string baseFileName = requestId.ToString() + lineNumber.ToString();
    string fileDownloadName = baseFileName + DateTime.Now.ToString("ddMMyyyy");
    string filePathBase = Path.Combine(GetFilePath(), baseFileName);
    var supportedExts = new[] { "pdf", "doc", "docx" };

    try
    {
        // 遍历支持的扩展名,查找实际存在的文件
        foreach (var ext in supportedExts)
        {
            string fullPath = $"{filePathBase}.{ext}";
            if (System.IO.File.Exists(fullPath))
            {
                // 根据扩展名匹配对应的MIME类型
                string contentType = ext switch
                {
                    "pdf" => "application/pdf",
                    "doc" => "application/msword",
                    "docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                    _ => "application/octet-stream"
                };
                var stream = new FileStream(fullPath, FileMode.Open);
                return File(stream, contentType, $"{fileDownloadName}.{ext}");
            }
        }

        // 未找到对应文件时返回NotFound
        return NotFound("指定文件不存在");
    }
    catch (Exception ex)
    {
        // 服务器内部错误返回500状态码,避免泄露敏感信息
        return StatusCode(StatusCodes.Status500InternalServerError, "文件下载失败");
    }
}

二、Upload与Download方法的优化反馈

Upload方法优化点

  1. 路径拼接更安全:替换字符串拼接为Path.Combine,自动适配不同操作系统的路径分隔符
  2. 扩展名处理更严谨:先判断扩展名是否为空,再统一转为小写避免大小写问题,同时用HashSet提升格式校验效率
  3. 参数校验更完善:补充formFile为空的检查,避免空引用异常
  4. 异常处理更合理:生产环境下不返回原始异常信息,改为通用错误提示,同时建议添加日志记录
  5. 返回结果更规范:返回结构化对象,方便前端解析

修改后的Upload方法:

[HttpPost("Upload/{requestId}/{lineNumber}")]
public async Task<IActionResult> OnPostUploadAsync(IFormFile formFile, [FromRoute] long requestId, [FromRoute] int lineNumber)
{
    // 检查文件是否为空或无内容
    if (formFile == null || formFile.Length == 0)
    {
        return BadRequest("请选择有效的文件进行上传");
    }

    try
    {
        string docId = requestId.ToString() + lineNumber.ToString();
        string filepath = GetFilePath();
        var supportedTypes = new HashSet<string> { "doc", "docx", "pdf" };

        // 安全获取并处理文件扩展名
        string fileExt = Path.GetExtension(formFile.FileName).TrimStart('.').ToLowerInvariant();
        if (string.IsNullOrEmpty(fileExt) || !supportedTypes.Contains(fileExt))
        {
            return BadRequest("文件格式无效,仅支持DOC、DOCX、PDF格式");
        }

        // 拼接完整文件路径,自动创建目录(已存在则无操作)
        string concessionDocumentPath = Path.Combine(filepath, $"{docId}.{fileExt}");
        Directory.CreateDirectory(filepath);

        // 覆盖已存在的文件
        using (var stream = System.IO.File.Create(concessionDocumentPath))
        {
            await formFile.CopyToAsync(stream);
        }

        return Ok(new { Message = $"文件 {formFile.FileName} 上传成功", FileId = docId });
    }
    catch (Exception ex)
    {
        // 此处建议添加日志记录ex信息,方便排查问题
        return StatusCode(StatusCodes.Status500InternalServerError, "文件上传失败,请稍后重试");
    }
}

Download方法原有问题优化

  1. 移除硬编码的.pdf后缀,改为动态匹配实际文件
  2. 替换不安全的路径拼接方式,使用Path.Combine保证跨平台兼容性
  3. 修正异常状态码:文件不存在返回NotFound,服务器错误返回500,符合HTTP规范
  4. 动态设置MIME类型,确保浏览器能正确识别并处理不同格式的文件

三、通用优化建议

  • 添加日志:在异常分支中注入ILogger记录详细错误信息,便于后续排查问题
  • 文件大小限制:在Upload方法中添加文件大小校验,防止上传过大文件占用服务器资源
  • 权限控制:如果接口需要权限访问,添加[Authorize]属性实现身份验证与授权
  • 依赖注入规范:确保_environment通过构造函数注入,符合ASP.NET Core依赖注入设计原则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:35:21