gpt4 book ai didi

c# - 无法为内容类型多部分配置 Web API

转载 作者:可可西里 更新时间:2023-11-01 02:59:56 24 4
gpt4 key购买 nike

我正在研究 Web API - Web API 2。我的基本需求是创建一个 API 来更新用户的配置文件。在此,ios 和 android 将向我发送 multipart/form-data 中的请求。他们会给我发送一些带有图像的参数。但是每当我尝试创建 API 时,我的模型每次都会变为 null。

我还在 WebApiConfig 中添加了这一行:

config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("multipart/form-data"));

这是我的课:

public class UpdateProfileModel
{
public HttpPostedFileBase ProfileImage { get; set; }
public string Name { get; set; }
}

这是我的 Controller :

[Route("api/Account/UpdateProfile")]
[HttpPost]
public HttpResponseMessage UpdateProfile(UpdateProfileModel model)
{
}

我什至没有在我的模型中获取参数值。我做错了什么吗?

与此相关的答案都对我没有帮助。大约是第 3 天,我几乎尝试了所有方法。但我无法实现它。

虽然我可以使用它,但如下所示,但这似乎不是一个好方法。所以我正在避免它。

var httpRequest = HttpContext.Current.Request;
if (httpRequest.Form["ParameterName"] != null)
{
var parameterName = httpRequest.Form["ParameterName"];
}

对于文件我可以这样做:

if (httpRequest.Files.Count > 0)
{
//I can access my files here and save them
}

如果您有任何好的方法,请提供帮助或者请向我解释为什么我无法在模型中获取这些值。

非常感谢

最佳答案

JPgrassi 提供的答案是您将如何处理多部分数据。我觉得需要补充的东西不多,所以我想到自己写一个答案。

MultiPart 表单数据,顾名思义,不是单一类型的数据,而是指定表单将作为MultiPart MIME 消息发送,因此您无法通过预定义的格式化程序来读取所有内容。您需要使用 ReadAsync 函数来读取字节流并获取不同类型的数据,识别它们并反序列化它们。

阅读内容有两种方式。第一种是读取所有内容并将其保存在内存中,第二种方法是使用提供程序将所有文件内容流式传输到一些随机命名的文件(带有 GUID)并以本地路径的形式提供句柄以访问文件(提供的示例由 jpgrassi 正在做第二个)。

第一种方法:将所有内容保存在内存中

//Async because this is asynchronous process and would read stream data in a buffer. 
//If you don't make this async, you would be only reading a few KBs (buffer size)
//and you wont be able to know why it is not working
public async Task<HttpResponseMessage> Post()
{

if (!request.Content.IsMimeMultipartContent()) return null;

Dictionary<string, object> extractedMediaContents = new Dictionary<string, object>();

//Here I am going with assumption that I am sending data in two parts,
//JSON object, which will come to me as string and a file. You need to customize this in the way you want it to.
extractedMediaContents.Add(BASE64_FILE_CONTENTS, null);
extractedMediaContents.Add(SERIALIZED_JSON_CONTENTS, null);

request.Content.ReadAsMultipartAsync()
.ContinueWith(multiPart =>
{
if (multiPart.IsFaulted || multiPart.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, multiPart.Exception);
}

foreach (var part in multiPart.Result.Contents)
{
using (var stream = part.ReadAsStreamAsync())
{
stream.Wait();
Stream requestStream = stream.Result;

using (var memoryStream = new MemoryStream())
{
requestStream.CopyTo(memoryStream);
//filename attribute is identifier for file vs other contents.
if (part.Headers.ToString().IndexOf("filename") > -1)
{
extractedMediaContents[BASE64_FILE_CONTENTS] = memoryStream.ToArray();
}
else
{
string jsonString = System.Text.Encoding.ASCII.GetString(memoryStream.ToArray());
//If you need just string, this is enough, otherwise you need to de-serialize based on the content type.
//Each content is identified by name in content headers.
extractedMediaContents[SERIALIZED_JSON_CONTENTS] = jsonString;
}
}
}
}
}).Wait();

//extractedMediaContents; This now has the contents of Request in-memory.
}

第二种方法:使用提供者(由 jpgrassi 提供)

请注意,这只是文件名。如果你想处理文件或存储在不同的位置,你需要再次流式读取文件。

 public async Task<HttpResponseMessage> Post()
{
HttpResponseMessage response;

//Check if request is MultiPart
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
//This specifies local path on server where file will be created
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);

//This write the file in your App_Data with a random name
await Request.Content.ReadAsMultipartAsync(provider);

foreach (MultipartFileData file in provider.FileData)
{
//Here you can get the full file path on the server
//and other data regarding the file
//Point to note, this is only filename. If you want to keep / process file, you need to stream read the file again.
tempFileName = file.LocalFileName;
}

// You values are inside FormData. You can access them in this way
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}

//Or directly (not safe)
string name = provider.FormData.GetValues("name").FirstOrDefault();


response = Request.CreateResponse(HttpStatusCode.Ok);

return response;
}

关于c# - 无法为内容类型多部分配置 Web API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34101258/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com