IHttpHandler file transfer Progress?

落花浮王杯 提交于 2019-12-13 00:38:30

问题


I have a simple IHttpHandler for chunked file transfer, and in the client code i'd like to report progress of percentage of the file, in the past I did it by dividing the amount of bytes transferred by the file size in bytes, and then make an event when it reached every 10% which I know is not the best method. I pulled out all that code regardless, but is there a better way to do it in the method I am using below?

//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();
                }

My server end code is here: This is probably the best place to report the progress as i can update to SQL locally here.

  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



    }

回答1:


Once you have handler you can easily do progress. Below sample code:

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

In code you have methods that fires events which you can subscribe:

    /// <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);
        }
    }


来源:https://stackoverflow.com/questions/10471127/ihttphandler-file-transfer-progress

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!