How to handle files in MultipartFormDataContent in .NET Core WebApi
In the previous article (How to handle MultipartFormDataContent in .NET Core WebApi), we described how to handle MultipartFormDataContent in .NET Core WebApi in the simplest way. Based on the framework-level encapsulation, we can quickly get the file content and text content respectively from Request.Form, but these default parsing methods are built and parsed in standard data formats on the front and back ends.
Problem Description
The example above shows the Request content received by the corresponding backend interface when the user sends a request through the IOS client. From the overall result of the request content, we can see that this is a multipart/form-data data format. Since this data is composed of multiple multipart sections, we can see that the request body contains 3 section, name values are Agree, CultureCode, FingerSignature respectively. Each section will contain a Content-Disposition field. The first two sections are ordinary data formats, and the last one is image type data. When the backend interface receives such a request body and tries to use Request.Form.Files to obtain the target file, it is found that the file content corresponding to FingerSignature cannot be obtained.
Problem Analysis
Through communication with the customer, we learned that the files corresponding to FingerSignature will be put together in the request body and passed to the backend. The customer said that the logic of the front-end APP has not been upgraded to ASP.NET Core (in Framework) at the backend. stage) can work normally. By looking at the assignment logic of Request.Form in ASP.NET Core: FormFeature implementation, we found the following logical function:
Through the logic of the source code, we can see that only the Content-Disposition corresponding to the current section contains both form-data and fileName (or fileNameStar) will be processed as a file (example: form-data; name= “FingerSignature”; fileName=”xxxx.jpeg”), otherwise the corresponding Section will not be added to Request.Form.Files. At this time, combined with the request content obtained above, it is located in the Content-Disposition of the FingerSignature part. Due to the lack of the fileName field, the backend cannot parse the corresponding file as the Root Cause of the issue.
Solution
Since the front-end APP has been released in multiple versions, letting the front-end complete this field is obviously not a reliable fix, so the back-end needs to do a compatibility process. When encountering this kind of file content that is not in a standard format, you need to use the MultipartReader object to process the Section content corresponding to the MultipartFormDataContent (actually the underlying logic of Request.Form.Files is to use the MultipartReader to parse each Section content in turn ). A method is implemented here to get all files in the current MultipartFormDataContent:
There are two details that need to be paid attention to in this method.
- By default, the content in Request.Body is only allowed to be read once, so we need to enable the EnableBuffering setting in the route where this method is used. Here you can customize a Filter to reuse this Characteristics:
- Because EnableBuffering is turned on for Request.Body, when the ReadFilesAsyns method is called, it is not sure that the starting position of the Stream in the Body is 0 at this time. So we need to reset the Stream’s Position to 0 through the Seek method before and after reading the Body.
Optimization Suggestions
From the current repair plan, the back-end only provides a compromise repair plan to adapt to the incomplete data of the front-end. Therefore, I feel that a more complete repair plan is for the front-end to send multipart/form-data data. When doing this, try to structure each Section content in a standard way, especially file types. If both the front and back ends can interact in a unified data format, the above-mentioned problems will naturally not occur, and the potential risks will naturally become smaller.