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

.NET Core 6下C#大文件上传Web API转F#报错求解

.NET Core 6 大文件上传Web API F# 正确实现

核心语法修正点

转换过程中两类高频编译错误对应F#语法规则如下:

  • 所有C#中带out参数的TryParse类方法,F#会自动封装为返回**(解析成功布尔值, 解析结果对象)**的元组,不需要提前声明out变量传入,直接解构元组即可拿到结果
  • F#的task{}计算表达式中,用let!绑定异步返回值、do!执行无返回值的异步操作,等价于C#的await关键字,不要直接套用C#的await写法
  • 循环读取流程中需要反复修改的变量用mutable关键字声明,赋值使用<-操作符
  • 控制器返回不同类型的响应结果时,需要显式向上转型为IActionResult统一类型,否则会触发类型不匹配编译错误

完整可运行F#代码

代码完全对齐原C#实现的逻辑:无参动作、跳过默认模型绑定、直接读取请求体、用MultipartReader分块解析请求、流式读写不加载全量文件到内存,支持超大文件上传:

open Microsoft.AspNetCore.Mvc
open Microsoft.AspNetCore.WebUtilities
open Microsoft.Net.Http.Headers
open System
open System.IO
open System.Threading.Tasks

[<ApiController>]
[<Route("api/[controller]")>]
// 关闭默认请求大小限制,适配大文件上传
[<DisableRequestSizeLimit>]
[<RequestFormLimits(MultipartBodyLengthLimit = Int64.MaxValue, ValueLengthLimit = Int32.MaxValue)>]
type FileUploadController() =
    inherit ControllerBase()

    [<HttpPost("upload-large-file")>]
    member this.LargeFileUpload() : Task<IActionResult> =
        task {
            // 校验请求类型合法性
            let parseContentTypeRes, parsedContentType = MediaTypeHeaderValue.TryParse(this.Request.ContentType)
            if not parseContentTypeRes || not parsedContentType.MediaType.Equals("multipart/form-data", StringComparison.OrdinalIgnoreCase) then
                return this.BadRequest("仅支持multipart/form-data类型请求") :> IActionResult

            // 读取multipart请求边界
            let boundary = HeaderUtilities.RemoveQuotes(parsedContentType.Boundary).Value
            if String.IsNullOrWhiteSpace(boundary) then
                return this.BadRequest("请求缺少合法的multipart边界参数") :> IActionResult

            // 初始化分块读取器,直接绑定原始请求流,跳过默认模型绑定
            use multipartReader = new MultipartReader(boundary, this.Request.Body)
            // 自定义文件存储目录,可根据业务调整
            let saveDir = Path.Combine(Directory.GetCurrentDirectory(), "UploadFiles")
            Directory.CreateDirectory(saveDir) |> ignore
            let mutable successCount = 0
            let mutable currentSection = Unchecked.defaultof<MultipartSection>

            // 循环读取每个分块
            let! nextSection = multipartReader.ReadNextSectionAsync()
            currentSection <- nextSection
            while currentSection <> null do
                let parseDispRes, contentDisp = ContentDispositionHeaderValue.TryParse(currentSection.ContentDisposition)
                // 仅处理文件类型分块,忽略普通表单字段
                if parseDispRes && contentDisp.IsFileDisposition() then
                    let fileName = HeaderUtilities.RemoveQuotes(contentDisp.FileName.Value).Value
                    let targetFile = Path.Combine(saveDir, Path.GetFileName(fileName))
                    // 流式写入文件,缓冲区大小设为1MB,可自行调整
                    do!
                        use fileStream = File.Create(targetFile)
                        task {
                            let buffer = Array.zeroCreate<byte> (1024 * 1024)
                            let mutable readBytes = 0
                            let! firstRead = currentSection.Body.ReadAsync(buffer, 0, buffer.Length)
                            readBytes <- firstRead
                            while readBytes > 0 do
                                do! fileStream.WriteAsync(buffer, 0, readBytes)
                                let! nextRead = currentSection.Body.ReadAsync(buffer, 0, buffer.Length)
                                readBytes <- nextRead
                        } :> Task
                    successCount <- successCount + 1
                // 读取下一个分块
                let! next = multipartReader.ReadNextSectionAsync()
                currentSection <- next

            return this.Ok({| SuccessUploadCount = successCount; Msg = "上传完成" |}) :> IActionResult
        }

部署注意事项

如果你使用IIS、Nginx等反向代理托管服务,需要同步修改代理层的请求体大小限制,否则请求会在到达接口前被代理拦截。比如IIS需要在web.config中配置requestLimits节点的maxAllowedContentLength为你需要的阈值,Nginx需要调整client_max_body_size配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:48:17