从多部分/表格读取文件输入

我通过HTML表单将文件发布到WCF REST服务, enctype设置为multipart/form-data和单个组件: <input type="file" name="data"> 。 由服务器读取的结果流包含以下内容:

------WebKitFormBoundary
Content-Disposition: form-data; name="data"; filename="DSCF0001.JPG"
Content-Type: image/jpeg

<file bytes>
------WebKitFormBoundary--

问题是我不确定如何从流中提取文件字节。 我需要这样做才能将文件写入磁盘。


您可以查看以下博文,其中阐述了一种可用于使用Multipart Parser解析服务器上的multipart/form-data的技术:

public void Upload(Stream stream)
{
    MultipartParser parser = new MultipartParser(stream);
    if (parser.Success)
    {
        // Save the file
        SaveFile(parser.Filename, parser.ContentType, parser.FileContents);
    }
}

另一种可能是启用aspnet兼容性并使用HttpContext.Current.Request但这不是一个非常WCFish的方式。


对不起,迟到加入派对,但有一种方法可以通过微软公开API来实现

以下是您需要的内容:

  • System.Net.Http.dll
  • 包含在.NET 4.5中
  • 对于.NET 4,通过NuGet获取它
  • System.Net.Http.Formatting.dll
  • 对于.NET 4.5,获取这个NuGet包
  • 对于.NET 4,得到这个NuGet包
  • 注意 Nuget包中包含更多的程序集,但在编写本文时您只需要上述内容。

    一旦你引用了程序集,代码可以看起来像这样(为了方便,使用.NET 4.5):

    public static async Task ParseFiles(
        Stream data, string contentType, Action<string, Stream> fileProcessor)
    {
        var streamContent = new StreamContent(data);
        streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);
    
        var provider = await streamContent.ReadAsMultipartAsync();
    
        foreach (var httpContent in provider.Contents)
        {
            var fileName = httpContent.Headers.ContentDisposition.FileName;
            if (string.IsNullOrWhiteSpace(fileName))
            {
                continue;
            }
    
            using (Stream fileContents = await httpContent.ReadAsStreamAsync())
            {
                fileProcessor(fileName, fileContents);
            }
        }
    }
    

    至于用法,假设您有以下WCF REST方法:

    [OperationContract]
    [WebInvoke(Method = WebRequestMethods.Http.Post, UriTemplate = "/Upload")]
    void Upload(Stream data);
    

    你可以像这样实现它

    public void Upload(Stream data)
    {
        MultipartParser.ParseFiles(
               data, 
               WebOperationContext.Current.IncomingRequest.ContentType, 
               MyProcessMethod);
    }
    

    我在解析器方面遇到了一些问题,这些问题基于字符串解析,特别是对于大型文件,我发现它会耗尽内存,无法解析二进制数据。

    为了解决这些问题,我已经在这里打开了一个C#multipart / form-data解析器的尝试

    特征:

  • 处理非常大的文件。 (数据流入并在读取时流出)
  • 可以处理多个文件上传,并自动检测某个部分是否为文件。
  • 以文件流的形式返回文件而不是byte [](适用于大文件)。
  • 包含MSDN风格生成的网站的库的完整文档。
  • 完整的单元测试。
  • 限制:

  • 不处理非多部分数据。
  • 然后代码更复杂洛伦佐的
  • 只需使用MultipartFormDataParser类即可:

    Stream data = GetTheStream();
    
    // Boundary is auto-detected but can also be specified.
    var parser = new MultipartFormDataParser(data, Encoding.UTF8);
    
    // The stream is parsed, if it failed it will throw an exception. Now we can use
    // your data!
    
    // The key of these maps corresponds to the name field in your
    // form
    string username = parser.Parameters["username"].Data;
    string password = parser.Parameters["password"].Data
    
    // Single file access:
    var file = parser.Files.First();
    string filename = file.FileName;
    Stream data = file.Data;
    
    // Multi-file access
    foreach(var f in parser.Files)
    {
        // Do stuff with each file.
    }
    

    在WCF服务的上下文中,你可以像这样使用它:

    public ResponseClass MyMethod(Stream multipartData)
    {
        // First we need to get the boundary from the header, this is sent
        // with the HTTP request. We can do that in WCF using the WebOperationConext:
        var type = WebOperationContext.Current.IncomingRequest.Headers["Content-Type"];
    
        // Now we want to strip the boundary out of the Content-Type, currently the string
        // looks like: "multipart/form-data; boundary=---------------------124123qase124"
        var boundary = type.Substring(type.IndexOf('=')+1);
    
        // Now that we've got the boundary we can parse our multipart and use it as normal
        var parser = new MultipartFormDataParser(data, boundary, Encoding.UTF8);
    
        ...
    }
    

    或者像这样(稍微慢一些,但代码更友好):

    public ResponseClass MyMethod(Stream multipartData)
    {
        var parser = new MultipartFormDataParser(data, Encoding.UTF8);
    }
    

    文档也可用,当您克隆存储库时,只需导航到HttpMultipartParserDocumentation/Help/index.html

    链接地址: http://www.djcxy.com/p/75395.html

    上一篇: Reading file input from a multipart/form

    下一篇: upload video to XAMPP