2016-09-21 1 views
0

Ich erstelle eine iOS- (und später Android-) App mit Xamarin, mit der der Benutzer ein Video aufzeichnen und auf POST an eine Web-API hochladen kann Ich habe an Ort und Stelle.Große Videodateien können nicht über WebClient auf den WebApi hochgeladen werden.UploadFileTaskAsync

Wenn ich die Anwendung auf einem Gerät im Debug-Modus ausführe, kann ich den Fortschritt der Datei sehen, die hochgeladen wird, aber sie stoppt möglicherweise, bevor die Datei vollständig hochgeladen wird. Es werden jedoch keine Ausnahmen ausgelöst und die App wird einfach beendet. Nichts in der Anwendungsausgabe, nichts im iOS-Protokoll und keine Fehler im Debugger. Es ist einfach weg.

Ich habe Fiddler verwendet, um eine Datei ähnlicher Größe über einen POST an den gleichen Web-API-Endpunkt zu senden, und es funktioniert einwandfrei. Ich kann über die App nichts über ungefähr 20 MB hochladen, kann aber Dateien mit 30 MB, 50 MB und größer mit Fiddler hochladen.

Meine Web.Config-Datei ist so eingestellt, dass 100 MB Dateiuploads in RequestFiltering und HttpRuntime zulässig sind.

Gibt es irgendwo anders ich kann sehen, was diesen Absturz verursacht? Von dem, was ich getestet habe, habe ich es isoliert, um den WebClient.UploadFileTaskAsync-Methodenaufruf zu isolieren, und es scheint etwa 21 MB zu sein, wo der Absturz beginnt. Dateien> 21 MB können während des Uploads zwischen 10 und 20 MB fehlen, während eine 20 MB-Datei den ganzen Weg bis zu 20 MB durchmacht (weiter als dort, wo die größere Datei fehlschlägt).

Hier ist meine Datei Uploader Abhängigkeitsdienst:

[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; 
     } 
    } 
} 
} 

EDIT: Ich fand heraus, dass ich diese auf meinem Simulator durch Hochladen einer größeren Stichprobe Videodatei als die sehr kleine, die ich als Platzhalter verwendet testen konnte, wenn Die Kamera ist nicht verfügbar. Die App stürzt noch (nicht im Debugger, nur sperrt vollständig nach oben), aber ich bekomme diese abgefangene Ausnahme (auch wenn ich einen try/catch-Block habe):

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 

Diese Referenzen diese Codezeilen, die ist, wo der Upload geschieht ...

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

EDIT:

ich habe versucht, meine Upload-Code-Zeile zu ändern, um nicht ausgeführt async und es läuft in Ordnung, aber ich muss jetzt warten, bis der Upload bevor es weiter bis zum Ende in der App (nicht akzeptabel):

Ich frage mich, ob ich eine Zeitüberschreitung habe, obwohl die Dokumentation, die ich lese, zeigt, dass ich anrufen und Methode abbrechen müsste, und dass es keine automatische Zeitüberschreitung für den asynchronen Anruf gibt. .. aber es scheint so, als ob das passiert.

BEARBEITEN: Ich funktionierte, indem ich zu UploadFile anstelle von UploadFileTaskAsync bewegte und die ganze Sache in eine Warte Task.Run wickelte. Ich bekomme keinen Zugriff mehr auf das Hochlade-Ereignis, aber es erledigt die Aufgabe. Ich würde gerne zur ursprünglichen Methode zurückkehren, wenn ich kann, aber bis ich herausfinde, was die Ausnahme verursacht, kann ich nicht gefangen werden, das funktioniert für mich ohne Benutzereinfluss.

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

Wie wäre es, Ihren Code zu 'Aufgabe byteResponse = client.UploadFileTaskAsync (Ziel, Filename) geändert wird; erwarten ByteResponse; if (byteResponse.Result) {Zeichenfolge response = System.Text.Encoding.UTF8.GetString (byteResponse.Result); } ' – Hackerman

Antwort

3

Dies ist nicht die richtige Antwort, die ich suchte, aber es funktioniert. Ich würde immer noch gerne UploadFileTaskAsync arbeiten, aber es scheint Timeout zu sein, also wickelte ich UploadFile() in eine Aufgabe.Run(), um es zum Laufen zu bringen (ohne einen Fortschrittsanzeiger jedoch):

Ich funktionierte, indem ich zu UploadFile anstelle von UploadFileTaskAsync bewegte und die gesamte Sache in eine Warteaufgabe einwarf. Ich bekomme keinen Zugriff mehr auf das Hochlade-Ereignis, aber es erledigt die Aufgabe. Ich würde gerne zur ursprünglichen Methode zurückkehren, wenn ich kann, aber bis ich herausfinde, was die Ausnahme verursacht, kann ich nicht gefangen werden, das funktioniert für mich ohne Benutzereinfluss.

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; 
     } 
Verwandte Themen