2016-09-21 93 views
0

我正在用Xamarin構建iOS(及更高版本的Android)應用程序,該應用程序允許用戶使用POST將Web視頻記錄到服務器並將其上傳到Web API我已經到位。大視頻文件無法通過WebClient.UploadFileTaskAsync上傳到WebApi

當我以調試模式在設備上運行應用程序時,我可以看到上傳文件的進度,但最終在文件完全上傳之前停止。但是,它不會拋出異常,並且應用程序退出。應用程序輸出中沒有任何內容,iOS日誌中沒有任何內容,調試器中也沒有錯誤。它剛剛消失。

我已經使用Fiddler通過POST發送一個類似大小的文件到相同的Web API端點,它工作正常。我無法通過應用上傳大約20MB的任何內容,但可以使用Fiddler成功上傳30MB,50MB和更大的文件。

我的Web.Config文件設置爲允許在RequestFiltering和HttpRuntime中上傳100MB文件。

有沒有其他地方我可以看看是什麼導致這次崩潰?從我測試過的東西中,我似乎已經將它隔離到了WebClient.UploadFileTaskAsync方法調用,並且它似乎在崩潰開始發生時的大約21 MB。文件> 21MB在上傳時失敗10到20MB,而20MB文件將一直到20MB(比大文件失敗的地方更遠)。

這裏是我的文件上傳依存服務:

[assembly: Dependency (typeof (FileUploader_iOS))] 
namespace GbrApps.iOS 
{ 
public class FileUploader_iOS: IFileUploader 
{ 
    public FileUploader_iOS() 
    { 
    } 
    public async Task<GbrAppVideo> UploadFileAsync(string FileName, int VideoId) 
    { 
     try 
     { 
     //Prepare to make a client ot the API 
     WebClient client = new WebClient(); 

     client.UploadProgressChanged += (object sender, UploadProgressChangedEventArgs e) => 
     { 
      //Upload progress changed as you see fit. 
      Console.WriteLine("Progress: {0}, Sent {1}, Total {2}",e.ProgressPercentage,e.BytesSent,e.TotalBytesToSend); 
      GlobalResources.UploadProgress = e.ProgressPercentage; 
     }; 

     //Get the file type, because the receiving end receives a generic "bodypart" type of file. 
     string[] splitFileName = FileName.Split('.'); 
     string FileType = splitFileName.Last().ToLower(); 

     //Prep the file upload URL 
     //Make sure your receiving end can handle big attachments if you're sending photos or video. 
     //ASP.NET can only handle 4MB files by 
     Uri destination = new Uri(string.Format("http://####.com/api/videos?VideoId={0}&FileType={1}&OS=IOS",VideoId,FileType)); 
     Console.WriteLine ("Uploading to " + destination.ToString()); 

     //Send the file and wait for a response asyncronously 
     byte[] byteResponse = await client.UploadFileTaskAsync(destination,FileName); 
     string response = System.Text.Encoding.UTF8.GetString (byteResponse); 

     //Parse the response as a JSON object 
     GbrAppVideo result = JsonConvert.DeserializeObject<GbrAppVideo>(response); 
     Console.WriteLine (string.Format ("Upload completed: {0}", result)); 

     //Delete the local file since we don't need it anymore 
     if (result.VideoId >0) { 
      File.Delete (FileName); 
     } 

     //Let the system know the video is done 
     GlobalResources.activeVideo = result; 

     //Return the uploader result object so code can continue and know what to do. 
     return result; 
      } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(ex.ToString()); 
      GlobalResources.activeVideo = new GbrAppVideo(); 
      return GlobalResources.activeVideo; 
     } 
    } 
} 
} 

編輯:我想通了,我可以上傳一個大樣本的視頻文件比非常小的一個我作爲一個佔位符,當測試這個對我的模擬器相機不可用。該應用程序仍然崩潰(而不是在調試器,只是完全鎖定了),但我得到這個未捕獲的異常(即使我有一個try/catch塊):

System.Net.WebException: An exception occurred during a WebClient request. 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() [0x0000c] in /Users/builder/data/lanes/3539/f37444ae/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/3539/f37444ae/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/3539/f37444ae/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 
    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/3539/f37444ae/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 
    at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult() [0x00000] in /Users/builder/data/lanes/3539/f37444ae/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:357 
    at GbrApps.iOS.FileUploader_iOS+<UploadFileAsync>c__async0.MoveNext() [0x00132] in /Users/chetcromer/Projects/GbrApp/GbrApps/iOS/gbrApi/FileUploader_iOS.cs:52 

此引用這行代碼,這是哪裏上傳發生......

byte[] byteResponse = await client.UploadFileTaskAsync(destination,FileName); 

編輯:

我試圖改變的代碼,我上傳的行不運行異步和它運行正常,但現在我必須等待上傳繼續之前完成在應用程序中(不可接受):

byte[] byteResponse = client.UploadFile(destination, FileName); 

我想知道是否有超時發生,即使我正在閱讀的文檔顯示我必須調用Abort方法,並且沒有異步調用的自動超時。 ..但它肯定似乎就是這樣發生的事情。

編輯:我得到了這個工作,通過移動到UploadFile而不是UploadFileTaskAsync並將所有東西包裹在await Task.Run中。我無法再訪問上傳進度事件,但它確實可以完成任務。如果可以的話,我想回到最初的方法,但是直到我發現什麼原因導致了我無法捕獲的異常,這對我沒有任何影響。

await Task.Run(() => 
      { 
       byte[] byteResponse = client.UploadFile(destination, FileName); 
       string response = System.Text.Encoding.UTF8.GetString(byteResponse); 

       //Parse the response as a JSON object 
       result = JsonConvert.DeserializeObject<GbrAppVideo>(response); 
       Console.WriteLine(string.Format("Upload completed: {0}", result)); 

       //Delete the local file since we don't need it anymore 
       if (result.VideoId > 0) 
       { 
        File.Delete(FileName); 
       } 

       //Let the system know the video is done 
       GlobalResources.activeVideo = result; 
      } 
+0

如何將您的代碼更改爲任務 byteResponse = client.UploadFileTaskAsync(destination,FileName);等待byteResponse; if(byteResponse.Result){string response = System.Text.Encoding.UTF8.GetString(byteResponse.Result); }' – Hackerman

回答

3

這不是我正在尋找的真正的答案,但它的工作原理。我仍然希望UploadFileTaskAsync正常工作,但似乎超時,所以我在Upload Task中包裝了UploadFile()。運行()讓它工作(但沒有進度指示器,但是):

我通過移動到UploadFile而不是UploadFileTaskAsync並將整個東西包裝在await Task.Run中得到了這個工作。我無法再訪問上傳進度事件,但它確實可以完成任務。如果可以的話,我想回到最初的方法,但是直到我發現什麼原因導致了我無法捕獲的異常,這對我沒有任何影響。

await Task.Run(() => 
     { 
      byte[] byteResponse = client.UploadFile(destination, FileName); 
      string response = System.Text.Encoding.UTF8.GetString(byteResponse); 

      //Parse the response as a JSON object 
      result = JsonConvert.DeserializeObject<GbrAppVideo>(response); 
      Console.WriteLine(string.Format("Upload completed: {0}", result)); 

      //Delete the local file since we don't need it anymore 
      if (result.VideoId > 0) 
      { 
       File.Delete(FileName); 
      } 

      //Let the system know the video is done 
      GlobalResources.activeVideo = result; 
     }