这些链接对我没有帮助:
例:
//Model: public class Group { public int Id { get; set; } public File File { get; set; } } //Controller: [HttpPost] public void SaveGroup([FromBody]Group group) {} //Formatter: public class MultipartFormFormatter : MediaTypeFormatter { private const string StringMultipartMediaType = "multipart/form-data"; public MultipartFormFormatter() { this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(StringMultipartMediaType)); } public override bool CanReadType(Type type) { return true; } public override bool CanWriteType(Type type) { return false; } public async override Task<object> ReadFromStreamAsync(Type type,Stream readStream,HttpContent content,IFormatterLogger formatterLogger) { //Implementation? What here should be? } }
ReadFromStreamAsync方法应该返回什么?
如何使它能够正确地将参数传递给动作?
解决方法
public class MultipartFormFormatter : FormUrlEncodedMediaTypeFormatter { private const string StringMultipartMediaType = "multipart/form-data"; private const string StringApplicationMediaType = "application/octet-stream"; public MultipartFormFormatter() { this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(StringMultipartMediaType)); this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(StringApplicationMediaType)); } public override bool CanReadType(Type type) { return true; } public override bool CanWriteType(Type type) { return false; } public override async Task<object> ReadFromStreamAsync(Type type,IFormatterLogger formatterLogger) { var parts = await content.ReadAsMultipartAsync(); var obj = Activator.CreateInstance(type); var propertiesFromObj = obj.GetType().GetRuntimeProperties().ToList(); foreach (var property in propertiesFromObj.Where(x => x.PropertyType == typeof(FileModel))) { var file = parts.Contents.FirstOrDefault(x => x.Headers.ContentDisposition.Name.Contains(property.Name)); if (file == null || file.Headers.ContentLength <= 0) continue; try { var fileModel = new FileModel(file.Headers.ContentDisposition.FileName,Convert.ToInt32(file.Headers.ContentLength),ReadFully(file.ReadAsStreamAsync().Result)); property.SetValue(obj,fileModel); } catch (Exception e) { } } foreach (var property in propertiesFromObj.Where(x => x.PropertyType != typeof(FileModel))) { var formData = parts.Contents.FirstOrDefault(x => x.Headers.ContentDisposition.Name.Contains(property.Name)); if (formData == null) continue; try { var strValue = formData.ReadAsStringAsync().Result; var valueType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; var value = Convert.ChangeType(strValue,valueType); property.SetValue(obj,value); } catch (Exception e) { } } return obj; } private byte[] ReadFully(Stream input) { var buffer = new byte[16 * 1024]; using (var ms = new MemoryStream()) { int read; while ((read = input.Read(buffer,buffer.Length)) > 0) { ms.Write(buffer,read); } return ms.ToArray(); } } } public class FileModel { public FileModel(string filename,int contentLength,byte[] content) { Filename = filename; ContentLength = contentLength; Content = content; } public string Filename { get; set; } public int ContentLength { get; set; } public byte[] Content { get; set; } }