2016-08-18 1 views
1

У меня есть элемент canvas на веб-сайте, который я загружаю с помощью API FormData. Вот как я это делаю:Как работает ReadAsMultipartAsync?

upload: function (e) { 
    var file = this.imagePreview.ui.canvas.get(0).toDataURL("image/jpeg") 
        .replace('data:image/jpeg;base64,', ''); 
    if (file) { 
     var formData = new FormData(); 
     formData.append('file', file); 
     $.ajax({ 
      url: app.getApiRoot + 'UserFiles/', 
      type: "post", 
      data: formData, 
      processData: false, 
      contentType: false, 
      error: function() { 
       $("#file_upload_result").html('there was an error while submitting'); 
      } 
     }); 
    } 
} 

где я заменить весь data:image/jpeg;base64, бизнес как за this post.

На внутреннем интерфейсе у меня есть следующий многослойную контроллер:

public async Task<IHttpActionResult> PostUserFile() 
{ 
    string imageDir = ConfigurationManager.AppSettings["UploadedImageDir"]; 
    var PATH = HttpContext.Current.Server.MapPath("~/" + imageDir); 
    var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty); 

    if (Request.Content.IsMimeMultipartContent()) 
    { 
     var streamProvider = new CustomMultipartFormDataStreamProvider(PATH); 
     await Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t => 
     { 
      if (t.IsFaulted || t.IsCanceled) 
      { 
       throw new HttpResponseException(HttpStatusCode.InternalServerError); 
      } 

      var files = streamProvider.FileData.Select(i => 
         { 
          var info = new FileInfo(i.LocalFileName); 
          return new UserFile(User.Identity.GetUserId(), info.Name, rootUrl + "/" + imageDir + "/" + info.Name, info.Length/1024); 
         }); 

      db.UserFiles.AddRange(files); 
      db.SaveChangesAsync(); 
     }); 

     return Ok(); 
    } 
    else 
    { 
     throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted")); 
    } 
} 

Где реализовать CustomMultipartFormDataStreamProvider следующим образом:

public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider 
{ 
    public CustomMultipartFormDataStreamProvider(string path) 
     : base(path) 
    { } 

    public override string GetLocalFileName(Headers.HttpContentHeaders headers) 
    { 
     var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? 
         headers.ContentDisposition.FileName : 
         "NoName"; 
     // This is here because Chrome submits files in quotation 
     // marks which get treated as part of the filename and get escaped 
     return name.Replace("\"\"", string.Empty); 
    } 
} 

К сожалению, FileData на streamProvider подают в метод ReadAsMultipartAsync пуст :

FileData count = 0

И еще одна вещь, я нахожу интересным является то, что загруженный двоичный файл уцелели, так как я заметил из окна часов:

Escaped data

%2f является последовательность символов для / характера.

Я просто не могу точно указать проблему. У кого-нибудь есть предложения?

ответ

0

Смешивание ContinueWith и async/await приводит к проблемам, просто выполните await Request.Content.ReadAsMultipartAsync(streamProvider);, и все в .ContinueWith просто пойдет после ожидания, как обычный код.

Или удалить асинхронный/ждать и добавить:

return Request.Content.ReadAsMultipartAsync(streamProvider).Continu‌​eWith... 

Также вы можете посмотреть по этой ссылке: Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME

+0

Пожалуйста, объясните ответ более подробно. –

+0

Пожалуйста, попробуйте узнать, как использовать Stackoverflow. Отредактируйте ответ, не добавляйте информацию в комментарии. Прочтите это: https://stackoverflow.com/help/how-to-answer –

+0

Звучит очень разумно. Позвольте мне реализовать это позже сегодня и вернуться к вам. – seebiscuit