[英].net API error when attempting to accept model with large file
I have an API method that receives a null model parameter when a large file is passed to it.我有一个 API 方法,当一个大文件传递给它时,它接收一个 null model 参数。
I created a test client to test this endpoint.我创建了一个测试客户端来测试这个端点。 Both the test client and the API have these same identical models and are using .NET 4.5:
测试客户端和 API 都具有相同的型号,并且使用的是 .NET 4.5:
public class FilingPostModel
{
public string Id { get; set; }
public string TypeId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Suffix { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Comment { get; set; }
public string DateSubmitted { get; set; }
public string Summary { get; set; }
public List<FilePostModel> FileData { get; set; }
}
public class FilePostModel
{
public string FileId { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
public string FileContent { get; set; }
public string DateSubmitted { get; set; }
public string ClassificationId { get; set; }
}
The test client is submitting this model:测试客户端正在提交此 model:
City: "j"
Comment: null
Country: "United States"
Email: "test@test.tst"
FileData: Count = 1
TypeId: "f94e264a-c8b1-44aa-862f-e6f0f7565e19"
FirstName: "fname"
Id: null
LastName: "lname"
Line1: "testdrive 1"
Line2: null
MiddleName: null
PhoneNumber: "3748923798"
PostalCode: "12345"
State: "Pennsylvania"
Suffix: null
Summary: null
The FileData component has one item: FileData 组件有一项:
FileContent: "xY+v6sC8RHQ19av2LpyFGu6si8isrn8YquwGRAalW/6Q..."
ClassificationId: null
ContentType: "text/plain"
FileName: "large.txt"
This is the test clients method used to create and send the API request这是用于创建和发送 API 请求的测试客户端方法
public async Task<ActionResult> PostNewFiling(FilingPostModel model)
{
Dictionary<string, string> req = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", "some user name"},
{"password", "some password"},
};
FilingApiPostModel postModel = new FilingApiPostModel(model);
using (HttpClient client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(15);
client.BaseAddress = new Uri(baseUrl);
var resp = await client.PostAsync("Token", new FormUrlEncodedContent(req));
if (resp.IsSuccessStatusCode)
{
TokenModel token = JsonConvert.DeserializeObject<TokenModel>(await resp.Content.ReadAsStringAsync());
if (!String.IsNullOrEmpty(token.access_token))
{
foreach (HttpPostedFileBase file in model.Files)
{
if (file != null)
{
FilePostModel fmodel = new FilePostModel();
fmodel.FileName = file.FileName;
fmodel.ContentType = file.ContentType;
byte[] fileData = new byte[file.ContentLength];
await file.InputStream.ReadAsync(fileData, 0, file.ContentLength);
fmodel.FileContent = Convert.ToBase64String(fileData);
fmodel.ClassificationId = model.Classification1;
postModel.FileData.Add(fmodel);
}
}
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.access_token);
var response = await client.PostAsJsonAsync("api/Filing/PostFiling", postModel);
var responseBody = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
return Json(new { responseBody });
else
return Json(new { error = true, message = "Error Uploading", obj = responseBody });
}
}
return Json(new { error = true, message = "Error Uploading" });
}
}
Here is the API method to receive this client request:这是接收此客户端请求的 API 方法:
public async Task<StatusModel> PostFiling(FilingPostModel model)
Here is the maxAllowedContentLength setting in web.config:这是 web.config 中的 maxAllowedContentLength 设置:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295" />
</requestFiltering>
</security>
</system.webServer>
The API model is always null
in this test scenario.在此测试场景中,API model 始终为
null
。 I'm receiving two types of errors:我收到两种类型的错误:
- Newtonsoft.Json - Array dimensions exceeded supported range
Newtonsoft.Json - 阵列尺寸超出支持范围
- Newtonsoft.Json - Unexpected character encountered while parsing value: x.
Newtonsoft.Json - 解析值时遇到意外字符:x。 Path 'FileData[0].Bytes', line 1, position 517
路径 'FileData[0].Bytes',第 1 行,position 517
The file size of this test file is 560 MB.该测试文件的文件大小为 560 MB。 I used Dummy File Creator to create it.
我使用Dummy File Creator来创建它。 Here's a sample of what the content looks like:
以下是内容的示例:
ůêÀ¼Dt5õ«ö.œ…Ȭ®ªìD¥[þ6\hW åz·cʾYP¸‡>•;,–@Ó¶ÿm™fø@ÃNÇIäÀ¿Y4~ëÆÃc¥EWÀ_÷õ9%«éÀG!WBÍ*G2P×æŸ7ú‚{ÓêRúÅîµMZSªšpt6ä”Òø˜H
I have also tried using "fsutil file createnew" to create a test file but receive similar error.我也尝试过使用“fsutil file createnew”来创建一个测试文件,但收到类似的错误。
Everything works properly when testing with a 256 MB file.使用 256 MB 文件进行测试时,一切正常。
Thank you for your help.谢谢您的帮助。
you can add two attributes to your action:您可以为您的操作添加两个属性:
[RequestFormLimits(MultipartBodyLengthLimit = 209715200)]
[FromBody]
If you need to post JSON I would change your FileData object to use a Base64 encoded string in place of the byte array.如果您需要发布 JSON 我会更改您的 FileData object 以使用 Base64 编码字符串代替字节数组。
Change the Bytes
property in FileData to a string and then when creating the request change fmodel.Bytes = fileData
to fmodel.Bytes = Convert.ToBase64String(fileData)
.将 FileData 中的
Bytes
属性更改为字符串,然后在创建请求时将fmodel.Bytes = fileData
更改为fmodel.Bytes = Convert.ToBase64String(fileData)
。
After deserialising your JSON you can convert the base64 back to a byte[] using Convert.FromBase64String(String)
.反序列化 JSON 后,您可以使用
Convert.FromBase64String(String)
将 base64 转换回 byte[] 。
Not only will this prevent you exceeding the array limit in JSON but will also reduce the payload size considerably.这不仅会阻止您超出 JSON 中的数组限制,而且还会大大减少有效负载大小。
Every implementation has its own limit for example PHP has 2MB by default you can increase it using Post_Max_Size每个实现都有自己的限制,例如 PHP 默认有 2MB,您可以使用 Post_Max_Size 增加它
ASP.NET Core enforces 30MB any file bigger than default limitation can cause errors. ASP.NET 内核强制执行 30MB 大于默认限制的任何文件都可能导致错误。
Here's Upload Large Files In ASP.NET Core !这是在 ASP.NET 内核中上传大文件!
For IIS Express, you need to add web.config to your project and add the following markup into it:对于 IIS Express,您需要将 web.config 添加到您的项目中,并在其中添加以下标记:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="209715200" />
</requestFiltering>
</security>
</system.webServer>
If the issue is being caused by the total size of the array, rather than the number of elements in the array, the OutOfMemoryException
might be avoided by targeting 64-bit compilation and by updating your app.config:如果问题是由数组的总大小而不是数组中的元素数量引起的,则可以通过针对 64 位编译和更新 app.config 来避免
OutOfMemoryException
:
<configuration>
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
</runtime>
</configuration>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.