我有一个简单的 IHttpHandler 用于分块文件传输,并且在客户端代码中我想报告文件百分比的进度,过去我通过将传输的字节数除以文件大小(以字节为单位)来做到这一点,然后当它达到每 10% 时进行一次事件,我知道这不是最好的方法。无论如何,我都提取了所有代码,但是在我下面使用的方法中有更好的方法吗?
//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
}