2017-06-01 103 views
0

我有一个.Net 4.5.2应用程序,我正在转向Dot Net Core。此应用程序允许用户上传包含元数据(Angular Client Side)的文件,Api将处理请求并处理文件。这是现有的代码。Dot Net Core中的MultipartMemoryStream

阿比

[HttpPost] 
[Route("AskQuestions")] 
public void ProvideClarifications(int id) 
{ 
    var user = base.GetUserLookup(); 
    if (user != null) 
    { 
    var streamProvider = new MultiPartStreamProvider(); 
    IEnumerable<HttpContent> parts = null; 
    Task.Factory 
     .StartNew(() => parts = Request.Content.ReadAsMultipartAsync(streamProvider).Result.Contents, 
      CancellationToken.None, 
      TaskCreationOptions.LongRunning, 
      TaskScheduler.Default) 
     .Wait(); 

     // do some stuff with streamProvider.FormData 
    } 
} 

提供商来处理文件和元数据

public class MultiPartStreamProvider : MultipartMemoryStreamProvider 
{ 
    private string _originalFileName = string.Empty; 
    public Dictionary<string, object> FormData { get; set; } 

    public byte[] ByteStream { get; set; } 

    public string FileName 
    { 
     get 
     { 
      return _originalFileName.Replace("\"", ""); 
     } 
    } 
    public MultiPartStreamProvider() 
    { 
     this.FormData = new Dictionary<string, object>(); 
    } 
    public override Task ExecutePostProcessingAsync() 
    { 
     foreach (var content in Contents) 
     { 
      var contentDispo = content.Headers.ContentDisposition; 
      var name = UnquoteToken(contentDispo.Name); 

      if (name.Contains("file")) 
      { 
       _originalFileName = UnquoteToken(contentDispo.FileName); 
       this.ByteStream = content.ReadAsByteArrayAsync().Result; 
      } 
      else 
      { 
       var val = content.ReadAsStringAsync().Result; 
       this.FormData.Add(name, val); 
      } 
     } 
     return base.ExecutePostProcessingAsync(); 
    } 
    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; 
    } 
} 
static class FormDataExtensions { 
    public static Object GetObject(this Dictionary<string, object> dict, Type type) 
    { 
     var obj = Activator.CreateInstance(type); 

     foreach (var kv in dict) 
     { 
      var prop = type.GetProperty(kv.Key); 
      if (prop == null) continue; 

      object value = kv.Value; 
      var targetType = IsNullableType(prop.PropertyType) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType; 

      if (value is Dictionary<string, object>) 
      { 
       value = GetObject((Dictionary<string, object>)value, prop.PropertyType); // <= This line     
      } 
      value = Convert.ChangeType(value, targetType); 
      prop.SetValue(obj, value, null); 
     } 
     return obj; 
    } 
    public static T GetObject<T>(this Dictionary<string, object> dict) 
    { 
     return (T)GetObject(dict, typeof(T)); 
    } 
    private static bool IsNullableType(Type type) 
    { 
     return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)); 
    } 
} 

所以这个工作完全正常目标框架,但在核心我就在这行异常

.StartNew(()=> parts = R equest.Content.ReadAsMultipartAsync(streamProvider).Result.Contents,

异常

'的HttpRequest' 不包含 '内容' 和没有扩展方法 '内容' 接受的第一定义可以找到'HttpRequest'类型的参数(您是否缺少使用指令或程序集引用?)

我需要什么来确保我可以获取此文件和元数据?核心方式是从HttpRequest获取HttpContent

回答

1

Asp.Net Core作为对内置多部分文件上载的支持。当您有List<IFormFile>参数时,模型绑定组件将使其可用。

有关详细信息,请参阅docs on file uploads,这里是相关的例子就给出了处理多上传:

[HttpPost("UploadFiles")] 
public async Task<IActionResult> Post(List<IFormFile> files) 
{ 
    long size = files.Sum(f => f.Length); 

    // full path to file in temp location 
    var filePath = Path.GetTempFileName(); 

    foreach (var formFile in files) 
    { 
     if (formFile.Length > 0) 
     { 
      using (var stream = new FileStream(filePath, FileMode.Create)) 
      { 
       await formFile.CopyToAsync(stream); 
      } 
     } 
    } 

    // process uploaded files 
    // Don't rely on or trust the FileName property without validation. 

    return Ok(new { count = files.Count, size, filePath}); 
} 
+0

感谢这个,所以我可以使用类似Request.Form.Files得到这个呢?我正在发送一个文件以及我需要从Request.Form –

+0

访问的元数据@MartinUllrich有没有理由按顺序同步处理文件,而不是一次等待所有任务? –

+0

啊,现在看起来不会有太大的区别,因为硬盘上的一切都会变成瓶颈。但是,为什么要将所有文件保存到同一位置? –