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 CustomMultipartFormDataStreamProvider
    Inherits MultipartFormDataStreamProvider
    
    Public Sub New(uploadPath As String)
        MyBase.New(uploadPath)
    End Sub
    
    Public Overrides Function GetLocalFileName(contentHeaders As HttpContentHeaders) As String
        If contentHeaders.ContentDisposition IsNot Nothing AndAlso
           Not 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 cleanFileName
        End If
        
        ' 默认行为(使用GUID)
        Return MyBase.GetLocalFileName(contentHeaders)
    End Function
End Class

使用自定义 Provider

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

Public Async Function ProcessUploadAsync(context As HttpContext) As Task
    Dim uploadPath = context.Server.MapPath("~/Uploads")
    If Not Directory.Exists(uploadPath) Then
        Directory.CreateDirectory(uploadPath)
    End If
    
    ' 使用自定义Provider
    Dim 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.FileData
        Dim 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 避免冲突,同时保留原始文件名的元数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专注VB编程开发20年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值