当前位置: 首页 > news >正文

asp.net自动保存上传文件时指定文件名,MultipartFormDataStreamProvider

Dim provider = New MultipartFormDataStreamProvider(uploadPath),在哪一行代码写入文件,如何设置保存的文件名

文件写入时机与自定义文件名的实现

在 MultipartFormDataStreamProvider 中,文件写入发生在调用 ReadAsMultipartAsync 方法期间。当解析器遇到文件内容时,会自动将其写入到指定目录。默认情况下,文件名由系统生成(通常是 GUID),但你可以通过自定义 Provider 来控制保存的文件名。

文件写入的具体位置

当执行以下代码时:vb

Await content.ReadAsMultipartAsync(provider)

MultipartFormDataStreamProvider 会:

  1. 解析请求内容
  2. 为每个文件创建临时文件(使用 GUID 命名)
  3. 将文件内容写入到这些临时文件
  4. 完成后,你可以通过 provider.FileData 访问文件元数据和本地路径

自定义保存的文件名

要控制保存的文件名,需继承 MultipartFormDataStreamProvider 并重写 GetLocalFileName 方法:vb

Public Class CustomMultipartFormDataStreamProviderInherits MultipartFormDataStreamProviderPublic Sub New(uploadPath As String)MyBase.New(uploadPath)End SubPublic Overrides Function GetLocalFileName(contentHeaders As HttpContentHeaders) As StringIf contentHeaders.ContentDisposition IsNot Nothing AndAlsoNot String.IsNullOrEmpty(contentHeaders.ContentDisposition.FileName) Then' 获取客户端上传的原始文件名Dim clientFileName = contentHeaders.ContentDisposition.FileName.Trim('"')' 清理文件名,移除非法字符Dim invalidChars = Path.GetInvalidFileNameChars()Dim cleanFileName = String.Join("_", clientFileName.Split(invalidChars))' 返回自定义文件名(保留扩展名)Dim fileExtension = Path.GetExtension(cleanFileName)Return $"{Guid.NewGuid()}{fileExtension}"  ' 使用GUID+原始扩展名' 或者直接使用原始文件名:Return cleanFileNameEnd If' 默认行为(使用GUID)Return MyBase.GetLocalFileName(contentHeaders)End Function
End Class

使用自定义 Provider

现在可以用自定义 Provider 控制文件名:

Public Async Function ProcessUploadAsync(context As HttpContext) As TaskDim uploadPath = context.Server.MapPath("~/Uploads")If Not Directory.Exists(uploadPath) ThenDirectory.CreateDirectory(uploadPath)End If' 使用自定义ProviderDim provider = New CustomMultipartFormDataStreamProvider(uploadPath)' 解析请求内容(此时文件会按自定义规则保存)Dim content = New StreamContent(context.Request.InputStream)content.Headers.ContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType)Await content.ReadAsMultipartAsync(provider)' 处理上传的文件For Each file In provider.FileDataDim fileInfo = New FileInfo(file.LocalFileName)Dim originalFileName = Path.GetFileName(file.Headers.ContentDisposition.FileName.Trim('"'))Console.WriteLine($"上传文件: {originalFileName}")Console.WriteLine($"  保存路径: {file.LocalFileName}")Console.WriteLine($"  大小: {fileInfo.Length} 字节")Next
End Function

文件名策略选择

  1. 使用 GUID(推荐)

    Return $"{Guid.NewGuid()}{fileExtension}"
    

    优点:避免文件名冲突,安全性高
    缺点:原始文件名丢失(但可通过元数据保留)

  2. 使用原始文件名

    Return cleanFileName
    

    优点:保留原始文件名
    缺点:可能导致文件覆盖,需处理重名问题

  3. 添加时间戳

    Return $"{DateTime.Now:yyyyMMddHHmmss}_{cleanFileName}"
    

    优点:减少冲突可能性
    缺点:文件名较长

关键注意事项

  1. 文件覆盖问题
    如果使用原始文件名,需检查文件是否已存在:

    Dim fullPath = Path.Combine(uploadPath, cleanFileName)
    If File.Exists(fullPath) Then' 添加序号或时间戳cleanFileName = $"{Path.GetFileNameWithoutExtension(cleanFileName)}_1{fileExtension}"fullPath = Path.Combine(uploadPath, cleanFileName)
    End If
    Return cleanFileName
    

    路径安全

  2. 永远不要直接使用客户端提供的文件名作为路径,防止目录遍历攻击:

    ' 错误(不安全):
    Return contentHeaders.ContentDisposition.FileName  ' 可能包含../等恶意路径' 正确(清理后):
    Return cleanFileName
    

    大文件处理

  3. 对于大文件,考虑在保存后移动到永久存储位置,或使用云存储服务(如 Azure Blob、AWS S3)。

总结

  • 文件写入时机:在 ReadAsMultipartAsync 执行期间自动写入。
  • 自定义文件名:通过继承 MultipartFormDataStreamProvider 并重写 GetLocalFileName 方法实现。
  • 最佳实践:使用 GUID 避免冲突,同时保留原始文件名的元数据。
http://www.xdnf.cn/news/484849.html

相关文章:

  • Flask框架入门与实践
  • LangPDF: Empowering Your PDFs with Intelligent Language Processing
  • YOLO11解决方案之对象裁剪探索
  • 大模型崛起:从技术突破到产业变革的深度解析
  • 【node】中间件
  • MySQL基础面试通关秘籍(附高频考点解析)
  • Promise.all 详解
  • java后端学习
  • 高效率者的特点
  • 三毛电视 1.0 | 央视、卫视、港澳台频道高清秒播,支持多种播放模式和电视投屏
  • C#数组与集合
  • 启用rvzi可视化自己的机器人发现joint state publisher gui没有滑块
  • Python多线程实战:提升并发效率的秘诀
  • 面向复杂环境的高性能通信接口芯片技术解析与应用
  • onvif支持H265
  • AI日报 · 2025年05月16日|Google DeepMind推出AlphaEvolve,能自主设计高级算法的编码代理
  • NFS服务
  • 【洗车店专用软件】佳易王洗车店多项目会员管理系统:一卡多用扣次软件系统实操教程 #扣次洗车管理软件
  • AUTOSAR图解==>AUTOSAR_SWS_ICUDriver_AUTOSAR_SWS_ICUDriver
  • matlab求解问题
  • 14、Python时间表示:Unix时间戳、毫秒微秒精度与time模块实战
  • Day 27 函数专题2 装饰器
  • 读取toml, 合并,生成新文件
  • Apollo Client 1.6.0 + @RefreshScope + @Value 刷新问题解析
  • volatile关键字详解
  • 淘宝商家层级存在流量上限怎么办,如何突破流量上限?
  • 梁文锋署名,DeepSeek-V3新论文揭秘:低成本大模型训练如何突破算力瓶颈?
  • 养生:健康生活的极简密码
  • P21-RNN-心脏病预测
  • blender中旋转模型,导入到threejs中带了旋转信息