Web API:使用 MultipartMemoryStreamProvider 时如何访问多部分表单值?

2023-12-07

我以前用过MultipartFormDataStreamProvider处理多部分请求。

由于我希望上传的文件存储在内存中,而不是磁盘文件中,因此我更改了代码以使用MultipartMemoryStreamProvider。文件加载似乎工作正常,但我无法再访问 其他形式的值可以通过provider.FormData under MultipartFormDataStreamProvider。有人可以告诉我该怎么做吗?

Fiddler捕获的原始请求:

POST http://myserver.com/QCCSvcHost/MIME/RealtimeTrans/ HTTP/1.1
Content-Type: multipart/form-data; boundary="XbCY"
Host: na-w-lxu3
Content-Length: 1470
Expect: 100-continue
Connection: Keep-Alive

--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=PayloadType

X12_270_Request_005010X279A1
--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=ProcessingMode

RealTime
--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=PayloadID

e51d4fae-7dec-11d0-a765-00a0c91e6fa6
--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=TimeStamp

2007-08-30T10:20:34Z
--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=SenderID

HospitalA
--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=ReceiverID

PayerB
--XbCY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=CORERuleVersion

2.2.0
--XbCY
Content-Disposition: form-data; name=Payload; filename=276_5010.edi

ISA*00*~SE*16*0001~GE*1*1~IEA*1*191543498~
--XbCY--

我的控制器代码:

string payload = null;
NameValueCollection nvc = null;
string fname = null;
StringBuilder sb = new StringBuilder();
sb.AppendLine();
foreach (StreamContent item in provider.Contents)
{
    fname = item.Headers.ContentDisposition.FileName;
    if (!String.IsNullOrWhiteSpace(fname))
    {
        payload = item.ReadAsStringAsync().Result;
    }
    else
    {
        nvc = item.ReadAsFormDataAsync().Result;
    }
}

更新于 2015 年 4 月 28 日

您可以根据以下内容创建自定义提供程序MultipartFormDataRemoteStreamProvider.
例子:

public class CustomMultipartFormDataProvider : MultipartFormDataRemoteStreamProvider
{
    public override RemoteStreamInfo GetRemoteStream(HttpContent parent, HttpContentHeaders headers)
    {
        return new RemoteStreamInfo(
            remoteStream: new MemoryStream(),
            location: string.Empty,
            fileName: string.Empty);
    }
}

Updated

自定义内存中 MultiaprtFormDataStreamProvider:

public class InMemoryMultipartFormDataStreamProvider : MultipartStreamProvider
{
    private NameValueCollection _formData = new NameValueCollection();
    private List<HttpContent> _fileContents = new List<HttpContent>();

    // Set of indexes of which HttpContents we designate as form data
    private Collection<bool> _isFormData = new Collection<bool>();

    /// <summary>
    /// Gets a <see cref="NameValueCollection"/> of form data passed as part of the multipart form data.
    /// </summary>
    public NameValueCollection FormData
    {
        get { return _formData; }
    }

    /// <summary>
    /// Gets list of <see cref="HttpContent"/>s which contain uploaded files as in-memory representation.
    /// </summary>
    public List<HttpContent> Files
    {
        get { return _fileContents; }
    }

    public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
    {
        // For form data, Content-Disposition header is a requirement
        ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
        if (contentDisposition != null)
        {
            // We will post process this as form data
            _isFormData.Add(String.IsNullOrEmpty(contentDisposition.FileName));

            return new MemoryStream();
        }

        // If no Content-Disposition header was present.
        throw new InvalidOperationException(string.Format("Did not find required '{0}' header field in MIME multipart body part..", "Content-Disposition"));
    }

    /// <summary>
    /// Read the non-file contents as form data.
    /// </summary>
    /// <returns></returns>
    public override async Task ExecutePostProcessingAsync()
    {
        // Find instances of non-file HttpContents and read them asynchronously
        // to get the string content and then add that as form data
        for (int index = 0; index < Contents.Count; index++)
        {
            if (_isFormData[index])
            {
                HttpContent formContent = Contents[index];
                // Extract name from Content-Disposition header. We know from earlier that the header is present.
                ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
                string formFieldName = UnquoteToken(contentDisposition.Name) ?? String.Empty;

                // Read the contents as string data and add to form data
                string formFieldValue = await formContent.ReadAsStringAsync();
                FormData.Add(formFieldName, formFieldValue);
            }
            else
            {
                _fileContents.Add(Contents[index]);
            }
        }
    }

    /// <summary>
    /// Remove bounding quotes on a token if present
    /// </summary>
    /// <param name="token">Token to unquote.</param>
    /// <returns>Unquoted token.</returns>
    private static string UnquoteToken(string token)
    {
        if (String.IsNullOrWhiteSpace(token))
        {
            return token;
        }

        if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
        {
            return token.Substring(1, token.Length - 2);
        }

        return token;
    }
}

Usage:

public async Task Post()
{
    if (!Request.Content.IsMimeMultipartContent("form-data"))
    {
        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

    var provider = await Request.Content.ReadAsMultipartAsync<InMemoryMultipartFormDataStreamProvider>(new InMemoryMultipartFormDataStreamProvider());

    //access form data
    NameValueCollection formData = provider.FormData;

    //access files
    IList<HttpContent> files = provider.Files;

    //Example: reading a file's stream like below
    HttpContent file1 = files[0];
    Stream file1Stream = await file1.ReadAsStreamAsync();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web API:使用 MultipartMemoryStreamProvider 时如何访问多部分表单值? 的相关文章

  • 重置 Windows Phone 照片上传

    我正在尝试使用 RestSharp 将照片上传到 Windows Phone 7 应用程序中的 REST api 进行获取 发布 post参数如下 photo 照片 编码为多部分 表单数据 照片 相册 id 现有相册的标识符 可以是一个事件
  • ApiController 操作无法从查询字符串解析数组

    使用 Visual Studio 2012 2 MVC4 Web 应用程序 我有请求发送到我的 ApiController 如下所示 http localhost api keys ids 1 ids 2 ids 3 我的印象是以下方法应该
  • 发生错误。", ExceptionMessage: "提供的 'HttpContent' 实例无效

    尝试将文件添加到 http 休息调用时出现此错误 responseJson 消息 发生错误 ExceptionMessage 提供了无效的 HttpContent 实例 它确实 正在使用 多部分 参数名称 内容 异常类型 System Ar
  • ASP.NET Web Api 2 中的异常处理

    Problem 我需要处理 Web api 2 异常并返回一个具有正确状态代码的丰富对象 401 表示未经授权 404 表示 ContentNotFound 等 以及一些额外信息作为内容 此外 我需要内容看起来像序列化的Exception对
  • WebApi 2 超出最大请求长度

    有谁知道是否有办法捕获此错误 本质上 我正在尝试实现一些功能 以允许用户将文件从网页上传到 webapi 控制器 这工作正常 但如果文件大小超过 web config 中指定的最大大小 服务器将返回 404 错误 我希望能够拦截此错误并返回
  • 使用restsharp序列化对象并将其传递给WebApi而不是序列化列表

    我有一个看起来像的视图模型 public class StoreItemViewModel public Guid ItemId get set public List
  • asp.net web api 自托管/owin/katana

    我对自托管有多个问题 自托管 Nuget 有 2 个 nuget 提供自托管 Microsoft AspNet WebApi OwinSelfHost and Microsoft AspNet WebApi SelfHost 那么微软有2种
  • 带有 @RequestBody 的 Spring 多部分文件

    我正在尝试将数据从应用程序上传到 Spring 后端服务 要上传的内容是一个 DataModel 其中包含要创建的对象的数据以及链接到该数据的多个图像 因此我使用这个方法签名 RequestMapping method RequestMet
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • jQuery 中的 Javascript .files[0] 属性

    jQuery 中是否有与此语句等效的语句 var value document getElementById id files 0 使用附加 files 0 的标准 jQuery 选择器似乎不起作用 并且我找不到与 files 等效的 jQ
  • 使用 App Insights 将相关 ID 添加到自动生成的遥测数据中

    我对 Application Insights 非常陌生 我正在考虑将其用于我计划使用 asp net webapi 实现的一组服务 我能够非常轻松地启动并运行基本遥测 右键单击 VS 上的项目 添加应用程序洞察 但随后我遇到了障碍 我计划
  • 从 ApiController 中的 json 序列化中排除属性

    我试图在 Web ApiControllers 中排除属性被序列化为 JSON 我已经验证了以下 2 个场景的工作原理 我已在我希望排除的属性中包含以下属性 System Web Script Serialization ScriptIgn
  • 通过查询字符串传递“Bearer”时 SignalR 身份验证失败

    我想在 SignalR 中启用身份验证 而服务器托管在 ASP NET WebAPI 中 我使用 OAuth Bearer 身份验证 客户端是 AngularJS 在客户端 我最初通过 HTTP 标头传递 Bearer 令牌 它与 WebA
  • WebAPI 和 Angular JS Excel 文件下载 - 文件损坏

    我正在 WebAPI 中生成 Excel 文件 我将其 存储 在内存流中 然后放入响应 如下所示 var result new HttpResponseMessage HttpStatusCode OK Content new Stream
  • 使 WebAPI 操作异步?

    我有一个问题 关于在 WebAPI MVC 控制器 AJAX 请求上使用 async await 是否有益 假设我有一个与 Web API 后端对话的 AngularJS 应用程序 并且我想获取一些数据 我对 Web API 进行了一些 A
  • 查询字符串模型绑定 ASP.NET WebApi

    我有以下型号 public class Dog public string NickName get set public int Color get set 我有以下通过 API 公开的 api 控制器方法 public class Do
  • 扩展授权属性

    我实施了 CustomAuthorization 属性基于 Authorize 属性 我的属性如下所示 public class CustomAuthorizeAttribute AuthorizeAttribute public eUse
  • 使用默认行为将模型绑定到接口

    我正在尝试将控制器操作绑定到接口 但仍保持默认的绑定行为 public class CoolClass ISomeInterface public DoSomething get set ISomeInterface public clas
  • Web.API MapHttpRoute 参数

    我的 Web API 路由遇到问题 我有以下两条路线 config Routes MapHttpRoute name MethodOne routeTemplate api controller action id type default
  • 如何检查DBContext是否已释放?

    我想与从外部 继承类 调用的另一个方法共享数据库上下文 而不创建新的上下文 除非正在释放它 我想检查上下文是否已处理 以便我可以创建新的上下文 这是休息 api 有多个实体的批量上传 我想共享事务 因此如果一个实体失败 它将不会提交到数据库

随机推荐