2014-05-06 2 views
1

Je suis en train de développer une application Windows Phone 8 qui doit télécharger des photos sur le stockage amazon s3. Cependant, je trouve que c'est impossible puisque le HttpClient expire après environ 60 secondes, quel que soit le paramètre de timeout que j'utilise.Windows Phone 8 Délai de téléchargement du fichier http post

Existe-t-il vraiment aucun moyen de télécharger de gros fichiers à partir de Windows Phone? BackgroundTransferRequest est inutile car il ne peut pas envoyer les métadonnées nécessaires avec les téléchargements de fichiers.

J'utilise ce code (qui fois sur):

using (var httpClient = new HttpClient()) 
{ 
    httpClient.Timeout = TimeSpan.FromMinutes(30); 
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, m_uploadUrl); 
    httpContent.Headers.Add("Keep-Alive", "true"); 
    request.Content = httpContent; // 3-5 Mb file 
    response = await httpClient.SendAsync(request); 
    statusCode = response.StatusCode; 
} 

J'ai aussi essayé PostAsync(), mais même résultat. Après environ 60 secondes, l'appel se termine avec un code d'état 400 ou 404. Il ne s'agit pas d'un délai d'expiration de serveur. Les applications iPhone et Android utilisent le même service. Aucun problème là-bas.

Des idées sur la façon de télécharger des fichiers qui prennent plus de 60 secondes à envoyer?

Répondre

0

J'ai moi aussi fait face à des choses similaires. Le problème de timeout. Vérifiez si vous pouvez utiliser une autre classe au lieu de HttpClient. WebClient peut l'être.

Vérifiez si cela vous aide: http://blog.anthonybaker.me/2013/06/how-to-upload-file-from-windows-phone.html

et même ceci: http://chriskoenig.net/2011/08/19/upload-files-from-windows-phone/

je suis arrivé des choses qui travaillent pour moi avec ceux-ci.

+0

J'ai essayé HttpWebRequest, mais le même problème là. Dès que je bande la bande passante, la demande échoue après 60 secondes. –

+0

Même j'avais fait des choses avec le HttpWebRequest. Fiddle beaucoup. Même problème. Temps libre. Exactement. J'ai même eu une classe avec tous les moyens possibles de communication http. :RÉ . Poster de toutes les manières, même synchrone et asynchrone. Même problème. Cependant, les moyens ci-dessus l'ont résolu pour moi. –

+0

Merci. Le premier lien n'est pas différent de ce que je fais. Je vais essayer le second (WebClient) et voir si c'est mieux –

0

J'ai utilisé plusieurs jours maintenant pour implémenter un nouvel uploader et obtenir tous les détails fonctionnels. J'ai utilisé HttpWebRequest avec les méthodes async et divisé le fichier en chuncks. Finalement, je l'ai fait fonctionner et il télécharge sans le temps mort. Voici le code complet:

using System; 
using Models; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace Services 
{ 
    public class UploadData 
    { 
     public Stream PostStream { get; set; } 
     public Stream FileStream { get; set; } 
     public byte[] HeaderBytes {get; set;} 
     public byte[] FooterBytes {get; set;} 
     public byte[] Buffer { get; set; } 
     public Photo Upload { get; set; } 
     public int BytesWritten { get; set; } 
    } 

    public class UploadEventArgs : EventArgs 
    { 
     public Photo Upload { get; set; } 
     public int Progress { get; set; } 
    } 

    public class UploadService 
    { 
     public delegate void CompletedEventHandler(object sender, UploadEventArgs e); 
     public event CompletedEventHandler UploadCompleted; 
     public delegate void ProgressEventHandler(object sender, UploadEventArgs e); 
     public event ProgressEventHandler ProgressChanged; 

     private static string contentType = "multipart/form-data; boundary={0}"; 
     private static string headerString = "Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\r\nContent-Type: Content-Type: application/octet-stream\r\n\r\n"; 
     private HttpWebRequest m_request; 
     private static string boundarystr; 

     private UploadData m_uploadData; 
     private bool m_isStopped; 

     public async Task StartUpload(Photo upload, Uri uri, Dictionary<string, string> parameters) 
     { 
      try 
      { 
       m_isStopped = false; 
       var fileStream = (await upload.File.OpenReadAsync()).AsStreamForRead(); 

       var uploadData = new UploadData(); 

       boundarystr = "---------------------------" + DateTime.Now.Ticks.ToString("x"); 
       string para = GetParamsString(parameters); 
       string headAndParams = para + String.Format(headerString, HttpUtility.UrlEncode(upload.File.Name)); 

       var headerBytes = System.Text.Encoding.UTF8.GetBytes(headAndParams); 
       var footerBytes = Encoding.UTF8.GetBytes("\r\n--" + boundarystr + "--\r\n"); 

       uploadData.Upload = upload; 
       uploadData.FileStream = fileStream; 
       uploadData.FooterBytes = footerBytes; 
       uploadData.HeaderBytes = headerBytes; 
       uploadData.BytesWritten = 0; 
       m_uploadData = uploadData; 
       m_request = (HttpWebRequest)WebRequest.Create(uri); 
       m_request.Method = "POST"; 
       m_request.AllowWriteStreamBuffering = false; 
       m_request.ContentType = string.Format(contentType, boundarystr); 
       m_request.ContentLength = fileStream.Length + headerBytes.Length + footerBytes.Length; 
       var asyncResult = m_request.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, uploadData); }, m_request); 
      } 
      catch (Exception ex) 
      { 
       m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
       m_uploadData.Upload.UploadInfo.Exception = new Exception("Start upload failed: " + ex.Message); 
       var argsStopped = new UploadEventArgs(); 
       argsStopped.Upload = m_uploadData.Upload; 
       m_uploadData.FileStream.Close(); 
       m_uploadData.PostStream.Close(); 
       OnUploadComplete(argsStopped); 
      } 
     } 

     private void GetRequestStreamCallback(IAsyncResult asynchronousResult, UploadData uploadData) 
     { 
      try 
      { 
       HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; 
       Stream postStream = request.EndGetRequestStream(asynchronousResult); 

       postStream.Write(uploadData.HeaderBytes, 0, uploadData.HeaderBytes.Length); 

       var args = new UploadEventArgs(); 
       args.Upload = uploadData.Upload; 
       args.Progress = 1; 
       OnProgressChanged(args); 
       uploadData.PostStream = postStream; 

       WriteNextChunck(uploadData); 
      } 
      catch (Exception ex) 
      { 
       m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
       m_uploadData.Upload.UploadInfo.Exception = new Exception("Header write failed: " + ex.Message); 
       var argsStopped = new UploadEventArgs(); 
       argsStopped.Upload = m_uploadData.Upload; 
       m_uploadData.FileStream.Close(); 
       m_uploadData.PostStream.Close(); 
       OnUploadComplete(argsStopped); 
      } 
     } 

     private void WriteNextChunck(UploadData upload) 
     { 
      try 
      { 
       if ((upload.FileStream.Length - upload.BytesWritten) >= 16 * 1024) 
       { 
        upload.Buffer = new byte[16 * 1024]; 
       } 
       else 
       { 
        // Last part 
        upload.Buffer = new byte[upload.FileStream.Length - upload.BytesWritten]; 
       } 

       upload.FileStream.Read(upload.Buffer, 0, (int)upload.Buffer.Length); 
       upload.PostStream.BeginWrite(upload.Buffer, 0, upload.Buffer.Length, BeginWriteCallback, upload); 
      } 
      catch (Exception ex) 
      { 
       m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
       m_uploadData.Upload.UploadInfo.Exception = new Exception("Buffer write failed: " + ex.Message); 
       var argsStopped = new UploadEventArgs(); 
       argsStopped.Upload = m_uploadData.Upload; 
       upload.FileStream.Close(); 
       upload.PostStream.Close(); 
       OnUploadComplete(argsStopped); 
      } 
     } 

     private void BeginWriteCallback(IAsyncResult ar) 
     { 
      try 
      { 
       var upload = ar.AsyncState as UploadData; 
       upload.PostStream.EndWrite(ar); 
       upload.BytesWritten += upload.Buffer.Length; 

       var args = new UploadEventArgs(); 
       args.Upload = upload.Upload; 
       args.Progress = (int)(((decimal)upload.BytesWritten/(decimal)upload.FileStream.Length) * 100); 
       OnProgressChanged(args); 

       if (m_isStopped) 
       { 
        upload.FileStream.Close(); 
        upload.PostStream.Close(); 
        m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
        m_uploadData.Upload.UploadInfo.Exception = new Exception("Upload stopped"); 
        var argsStopped = new UploadEventArgs(); 
        argsStopped.Upload = m_uploadData.Upload; 
        OnUploadComplete(argsStopped); 
        return; 
       } 

       // write next chunck 
       if (upload.BytesWritten < upload.FileStream.Length) 
       { 
        WriteNextChunck(upload); 
       } 
       if (upload.BytesWritten >= upload.FileStream.Length) 
       { 
        WriteFooter(upload); 
       } 
      } 
      catch (Exception ex) 
      { 
       m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
       m_uploadData.Upload.UploadInfo.Exception = new Exception("Upload write failed: " + ex.Message); 
       var argsStopped = new UploadEventArgs(); 
       argsStopped.Upload = m_uploadData.Upload; 
       OnUploadComplete(argsStopped); 
      } 
     } 

     private void WriteFooter(UploadData upload) 
     { 
      try 
      { 
       upload.PostStream.Write(upload.FooterBytes, 0, upload.FooterBytes.Length); 
       upload.PostStream.Close(); 
       var asyncResult = m_request.BeginGetResponse(new AsyncCallback(GetResponseCallback), m_request); 
      } 
      catch (Exception ex) 
      { 
       m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
       m_uploadData.Upload.UploadInfo.Exception = new Exception("Footer write failed: " + ex.Message); 
       var argsStopped = new UploadEventArgs(); 
       argsStopped.Upload = m_uploadData.Upload; 
       OnUploadComplete(argsStopped); 
      } 
     } 

     private void GetResponseCallback(IAsyncResult asynchronousResult) 
     { 
      try 
      { 
       HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; 
       HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult); 
       Stream streamResponse = response.GetResponseStream(); 
       StreamReader streamRead = new StreamReader(streamResponse); 
       string responseString = streamRead.ReadToEnd(); 
       streamResponse.Close(); 
       streamRead.Close(); 
       response.Close(); 

       m_uploadData.FileStream.Close(); 
       m_uploadData.Upload.UploadInfo.StatusCode = response.StatusCode; 

       if (response.StatusCode == HttpStatusCode.NoContent) 
       { 
        m_uploadData.Upload.UploadInfo.Exception = null; 
       } 
       else 
       { 
        m_uploadData.Upload.UploadInfo.Exception = new Exception(responseString); 
       } 
       var args = new UploadEventArgs(); 
       args.Upload = m_uploadData.Upload; 
       args.Progress = 100; 
       OnUploadComplete(args); 
      } 
      catch (Exception ex) 
      { 
       m_uploadData.Upload.UploadInfo.StatusCode = HttpStatusCode.NotFound; 
       m_uploadData.Upload.UploadInfo.Exception = ex; 
       var args = new UploadEventArgs(); 
       args.Upload = m_uploadData.Upload; 
       OnUploadComplete(args); 
      } 
     } 

     private string GetParamsString(Dictionary<string, string> parameters) 
     { 
      bool needsCLRF = false; 
      string result = ""; 
      foreach (var param in parameters) 
      { 
       // Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added. 
       // Skip it on the first parameter, add it to subsequent parameters. 
       if (needsCLRF) 
        result += "\r\n"; 

       needsCLRF = true; 

       string prm = string.Format("--{0}\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Disposition: form-data; name={1}\r\n\r\n{2}", 
         boundarystr, 
         param.Key, 
         param.Value); 
       result += prm; 

      } 

      // Add the end of the request. Start with a newline 
      string footer = "\r\n--" + boundarystr + "\r\n"; 
      result += footer; 

      return result; 
     } 

     protected virtual void OnUploadComplete(UploadEventArgs e) 
     { 
      if (UploadCompleted != null) 
       UploadCompleted(this, e); 
     } 

     protected virtual void OnProgressChanged(UploadEventArgs e) 
     { 
      if (ProgressChanged != null) 
       ProgressChanged(this, e); 
     } 

     public void Stop() 
     { 
      m_isStopped = true; 
     } 

    } 
}