2012-05-06 4 views
1

У меня есть простой IHttpHandler для пакетной передачи файлов, а в клиентском коде я хочу сообщить о прогрессе в процентах файла, в прошлом я сделал это, разделив количество байтов, переданных размером файла в байтах, а затем сделать событие, когда он достигнет 10%, что, как я знаю, не лучший метод. Я вытащил весь этот код независимо, но есть ли лучший способ сделать это в методе, который я использую ниже?Передача файла IHttpHandler Progress?

//IHTTPMethod 


       //Open file 
       string file = System.IO.Path.GetFileName(pubAttFullPath.ToString()); 
       FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); 
       //Chunk size that will be sent to Server 
       int chunkSize = 49152; 
       // Unique file name 
       string fileName = Guid.NewGuid() + Path.GetExtension(file); 
       int totalChunks = (int)Math.Ceiling((double)fileStream.Length/chunkSize); 
       // Loop through the whole stream and send it chunk by chunk; 
       for (int i = 0; i < totalChunks; i++) 
       { 
        int startIndex = i * chunkSize; 
        int endIndex = (int)(startIndex + chunkSize > fileStream.Length ? fileStream.Length : startIndex + chunkSize); 
        int length = endIndex - startIndex; 

        byte[] bytes = new byte[length]; 
        fileStream.Read(bytes, 0, bytes.Length); 


        //Request url, Method=post Length and data. 
        string requestURL = "http://localhost:16935/Transfer.ashx"; 
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestURL); 
        request.Method = "POST"; 
        request.ContentType = "application/x-www-form-urlencoded"; 

        // Chunk(buffer) is converted to Base64 string that will be convert to Bytes on the handler. 
        string requestParameters = @"fileName=" + fileName + @"&secretKey=mySecret" + 
        "&data=" + HttpUtility.UrlEncode(Convert.ToBase64String(bytes)); 

        // finally whole request will be converted to bytes that will be transferred to HttpHandler 
        byte[] byteData = Encoding.UTF8.GetBytes(requestParameters); 

        request.ContentLength = byteData.Length; 

        Stream writer = request.GetRequestStream(); 
        writer.Write(byteData, 0, byteData.Length); 
        writer.Close(); 
        // here we will receive the response from HttpHandler 
        StreamReader stIn = new StreamReader(request.GetResponse().GetResponseStream()); 
        string strResponse = stIn.ReadToEnd(); 
        stIn.Close(); 
       } 

Мой конец сервера код здесь: Это, вероятно, лучшее место, чтобы сообщить о достигнутом прогрессе, как я могу обновить до SQL локально здесь.

public class IHTTPTransfer : IHttpHandler 
    { 
     /// <summary> 
     /// You will need to configure this handler in the web.config file of your 
     /// web and register it with IIS before being able to use it. For more information 
     /// see the following link: http://go.microsoft.com/?linkid=8101007 
     /// </summary> 
     #region IHttpHandler Members 

     public bool IsReusable 
     { 
      // Return false in case your Managed Handler cannot be reused for another request. 
      // Usually this would be false in case you have some state information preserved per request. 
      get { return true; } 
     } 

     public void ProcessRequest(HttpContext context) 
     { 
      string accessCode = context.Request.Params["secretKey"].ToString(); 

      if (accessCode == "mySecret") 
      { 
       string fileName = context.Request.Params["fileName"].ToString(); 
       byte[] buffer = Convert.FromBase64String(context.Request.Form["data"]); 
       SaveFile(fileName, buffer); 
      } 
     } 

     public void SaveFile(string fileName, byte[] buffer) 
     { 
      string Path = @"C:\Filestorage\" + fileName; 
      FileStream writer = new FileStream(Path, File.Exists(Path) ? FileMode.Append : FileMode.Create, FileAccess.Write); 

      writer.Write(buffer, 0, buffer.Length); 
      writer.Close(); 
     } 

     #endregion 



    } 

ответ

0

После того, как у вас есть обработчик, вы можете легко добиться прогресса. Ниже пример код:

/// <summary> 
    /// The download file. 
    /// </summary> 
    /// <param name="state"> 
    /// The state. 
    /// </param> 
    /// <exception cref="InvalidDataException"> 
    /// </exception> 
    private void DownloadFile() 
    { 
     string url = "http://localhost:16935/Transfer.ashx"; 

     bool cancel = false; 
     string savePath = "C:/Temp"; 

     try 
     { 
      // Put the object argument into an int variable 
      int start = 0; 

      if (File.Exists(savePath)) 
      { 
       start = (int)new System.IO.FileInfo(savePath).Length; 
      } 

      // Create a request to the file we are downloading 
      var request = (HttpWebRequest)WebRequest.Create(url); 

      // Set the starting point of the request 
      request.AddRange(start); 

      // Set default authentication for retrieving the file 
      request.Credentials = CredentialCache.DefaultCredentials; 

      // Retrieve the response from the server 
      using (var response = (HttpWebResponse)request.GetResponse()) 
      { 
       // check file lenght 
       int fileLength = 0; 
       int.TryParse(resp.Headers.Get("Content-Length"), out fileLength); 

       // Open the URL for download 
       using (Stream responseStream = response.GetResponseStream()) 
       { 
        // Create a new file stream where we will be saving the data (local drive) 
        using (var fs = new FileStream(savePath, FileMode.Append, FileAccess.Write, FileShare.Read)) 
        { 
         // It will store the current number of bytes we retrieved from the server 
         int bytesSize; 

         // A buffer for storing and writing the data retrieved from the server 
         var downBuffer = new byte[2048]; 

         // Loop through the buffer until the buffer is empty 
         while ((bytesSize = responseStream.Read(downBuffer, 0, downBuffer.Length)) > 0) 
         { 
          var args = new CancelEventArgs(false); 
          this.OnCancel(args); 

          if (args.Cancel) 
          { 
           cancel = true; 
           break; 
          } 

          // Write the data from the buffer to the local hard drive 
          fs.Write(downBuffer, 0, bytesSize); 
          fs.Flush(); 

          float percentComplete = 0; 

          if (fileLength > 0) 
          { 
           percentComplete = (100 * fs.Length)/(float)fileLength; 

           if (percentComplete > 100) 
           { 
            percentComplete = 100; 
           } 
          } 

          this.OnProgressChanged(new ProgressChangedEventArgs((int)percentComplete)); 
         } 
        } 

       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw; 
     }    
    } 

В коде у вас есть методы, которые генерируют события, которые вы можете подписаться:

/// <summary> 
    /// Adds or removes cancel event. 
    /// </summary> 
    public event CancelEventHandler Cancel; 

    /// <summary> 
    /// Adds or removes progress changed event. 
    /// </summary> 
    public event EventHandler<ProgressChangedEventArgs> ProgressChanged; 

    /// <summary> 
    /// Raises progress changed event. 
    /// </summary> 
    /// <param name="e"> 
    /// <see cref="ProgressChangedEventArgs"/> params. 
    /// </param> 
    protected virtual void OnProgressChanged(ProgressChangedEventArgs e) 
    { 
     EventHandler<ProgressChangedEventArgs> handler = this.ProgressChanged; 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    /// <summary> 
    /// Raises cancel event. 
    /// </summary> 
    /// <param name="e"> 
    /// </param> 
    protected virtual void OnCancel(CancelEventArgs e) 
    { 
     CancelEventHandler handler = this.Cancel; 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 
Смежные вопросы