问题描述
我以前用MultipartFormDataStreamProvider来处理多部分请求。因为我要上传的文件被存储,而不是磁盘文件在内存中,我已经改变了我的code使用MultipartMemoryStreamProvider。该文件加载似乎工作正常,但我不再能够访问
其他形式的价值是能获得通过 provider.FormData code> MultipartFormDataStreamProvider下。可能有人告诉我怎么做呢?
原始请求由小提琴手捕获:
POST http://myserver.com/QCCSvcHost/MIME/RealtimeTrans/ HTTP / 1.1
内容类型:多重/ form-data的;边界=XbCY
主持人:NA-W-lxu3
内容长度:1470
期望:100-继续
连接:保持活动--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称= PayloadTypeX12_270_Request_005010X279A1
--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称= ProcessingMode即时的
--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称= PayloadIDe51d4fae-7dec-11D0-a765-00a0c91e6fa6
--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称=时间戳2007-08-30T10:20:34Z
--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称= SenderIDHospitalA
--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称= ReceiverIDPayerB
--XbCY
内容类型:text / plain的;字符集= UTF-8
内容处置:表格数据;名称= CORERuleVersion2.2.0
--XbCY
内容处置:表格数据;名称=净荷;文件名= 276_5010.ediISA * 00 *〜SE * 16 * 0001〜GE * 1 * 1〜国际能源署* 1 * 191543498〜
--XbCY--
我的控制器code:
字符串有效载荷= NULL;
雷士的NameValueCollection = NULL;
字符串FNAME = NULL;
StringBuilder的SB =新的StringBuilder();
sb.AppendLine();
的foreach(在provider.Contents StreamContent项)
{
FNAME = item.Headers.ContentDisposition.FileName;
如果(!String.IsNullOrWhiteSpace(FNAME))
{
有效载荷= item.ReadAsStringAsync()结果。
}
其他
{
雷士= item.ReadAsFormDataAsync()结果。
}
}
更新2015年4月28日
您可以创建基于 MultipartFormDataRemoteStreamProvider
自定义提供。结果
例如:
公共类CustomMultipartFormDataProvider:MultipartFormDataRemoteStreamProvider
{
公众覆盖RemoteStreamInfo GetRemoteStream(HttpContent父母,HttpContentHeaders头)
{
返回新RemoteStreamInfo(
remoteStream:新的MemoryStream()
位置:的String.Empty,
文件名:的String.Empty);
}
}
更新
自定义在内存MultiaprtFormDataStreamProvider:
公共类InMemoryMultipartFormDataStreamProvider:MultipartStreamProvider
{
私人的NameValueCollection _formData =新的NameValueCollection();
私人列表< HttpContent> _fileContents =新的List< HttpContent>(); 其中HttpContents的//设置指标,我们指定为表单数据
私人收藏<布尔> _isFormData =新的收集和LT;布尔>(); ///<总结>
///获取<见CREF =NameValueCollection中/>形式的数据通过作为多部分形式的数据的一部分。
///< /总结>
公众的NameValueCollection FORMDATA
{
{返回_formData; }
} ///<总结>
///获取的&LT名单;见CREF =HttpContent/> S包含上传的文件在内存中重新presentation。
///< /总结>
公开名单< HttpContent>档
{
{返回_fileContents; }
} 公共覆盖流GetStream(HttpContent父母,HttpContentHeaders头)
{
//对于表单数据,内容处理标头是必需的
ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
如果(contentDisposition!= NULL)
{
//我们将发布这个过程作为表单数据
_isFormData.Add(String.IsNullOrEmpty(contentDisposition.FileName)); 返回新的MemoryStream();
} //如果没有Content-Disposition头是present。
抛出新的InvalidOperationException异常(的String.Format(找不到所需的{0}在MIME多主体部分头字段..,内容处置));
} ///<总结>
///读非文件的内容的表单数据。
///< /总结>
///<&回报GT;< /回报>
公共覆盖异步任务ExecutePostProcessingAsync()
{
//寻找非文件HttpContents的实例,异步阅读
//得到字符串内容,然后添加的表单数据
对于(INT指数= 0;指数 - LT; Contents.Count;指数++)
{
如果(_isFormData [指数])
{
HttpContent formContent =目录[指数]
//提取从内容处置头名。我们知道,从早期的标头是present。
ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
字符串formFieldName = UnquoteToken(contentDisposition.Name)?的String.Empty; //读取内容作为字符串数据,并添加表单数据
字符串formFieldValue =等待formContent.ReadAsStringAsync();
FormData.Add(formFieldName,formFieldValue);
}
其他
{
_fileContents.Add(目录[指数]);
}
}
} ///<总结>
///令牌上删除边界的报价,如果present
///< /总结>
///< PARAM NAME =令牌>令牌来解除引用< /参数>
///<退货和GT;非上市令牌LT; /回报>
私人静态字符串UnquoteToken(字符串标记)
{
如果(String.IsNullOrWhiteSpace(标记))
{
返回记号。
} 如果(token.StartsWith(\\,StringComparison.Ordinal)及&放大器; token.EndsWith(\\,StringComparison.Ordinal)及&放大器; token.Length→1)
{
返回token.Substring(1,token.Length - 2);
} 返回记号。
}
}
用法
公共异步任务后()
{
如果(!Request.Content.IsMimeMultipartContent(表单数据))
{
抛出新的Htt presponseException(的HTTPStatus code.BadRequest);
} VAR提供商=等待Request.Content.ReadAsMultipartAsync< InMemoryMultipartFormDataStreamProvider>(新InMemoryMultipartFormDataStreamProvider()); //获取表单数据
NameValueCollection中FORMDATA = provider.FormData; //访问文件
IList的< HttpContent>文件= provider.Files; //例:读文件的流如下图所示
HttpContent文件1 =文件[0];
流file1Stream =等待file1.ReadAsStreamAsync();
}
I used to use MultipartFormDataStreamProvider to process multipart requests. Since I want the uploaded file to be stored in memory, instead of a disk file, I've changed my code to use MultipartMemoryStreamProvider. The file loading seems to be working fine but I am no longer able to accessother form values which were available through provider.FormData
under MultipartFormDataStreamProvider. Could someone show me how to do this?
The raw request captured by 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--
My controller code:
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;
}
}
Updated 4/28/2015
You could create a custom provider based on MultipartFormDataRemoteStreamProvider
.
Example:
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
Custom In-memory 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();
}
这篇关于网页API:如何使用MultipartMemoryStreamProvider时访问多部分表单值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!