使用multipart / body web请求跟踪多个文件上传的上传进度

时间:2016-07-08 16:10:11

标签: c# file-upload httpwebrequest

我使用HttpWebRequest将文件上传到服务器。请求将2个文件发送到服务器,视频文件和图像文件。我试图跟踪整个进度的进度,但问题是,进度日志是为每个文件上传单独运行的。我希望上传仅显示一次进度,但我无法弄清楚如何进行上传。这是我的客户端代码:

Dictionary<string, string> fields = new Dictionary<string, string>();
        fields.Add("username", username);

        HttpWebRequest hr = WebRequest.Create(url) as HttpWebRequest;
        hr.Timeout = 500000;
        string bound = "----------------------------" + DateTime.Now.Ticks.ToString("x");
        hr.ContentType = "multipart/form-data; boundary=" + bound;
        hr.Method = "POST";
        hr.KeepAlive = true;
        hr.Credentials = CredentialCache.DefaultCredentials;

        byte[] boundBytes = Encoding.ASCII.GetBytes("\r\n--" + bound + "\r\n");
        string formDataTemplate = "\r\n--" + bound + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

        Stream s = hr.GetRequestStreamWithTimeout(1000000);

        foreach (string key in fields.Keys)
        {
            byte[] formItemBytes = Encoding.UTF8.GetBytes(
                string.Format(formDataTemplate, key, fields[key]));
            s.Write(formItemBytes, 0, formItemBytes.Length);
        }

        s.Write(boundBytes, 0, boundBytes.Length);

        string headerTemplate =
            "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";

        List<string> files = new List<string> { fileUrl, thumbUrl };
        List<string> type = new List<string> { "video", "thumb" };

        int count = 0;
        foreach (string f in files)
        {
            var m = Path.GetFileName(f);
            var t = type[count];
            var j = string.Format(headerTemplate, t, m);
            byte[] headerBytes = Encoding.UTF8.GetBytes(
                string.Format(headerTemplate, type[count], Path.GetFileName(f)));

            s.Write(headerBytes, 0, headerBytes.Length);
            FileStream fs = new FileStream(f, FileMode.Open, FileAccess.Read);
            int bytesRead = 0;
            long bytesSoFar = 0;
            byte[] buffer = new byte[1024];
            while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
            {
                bytesSoFar += bytesRead;
                s.Write(buffer, 0, buffer.Length);
                Console.WriteLine(string.Format("sending file data {0:0.000}%", (bytesSoFar * 100.0f) / fs.Length));

            }

            s.Write(boundBytes, 0, boundBytes.Length);
            fs.Close();

            count += 1;
        }

        s.Close();

        string respString = "";
        hr.BeginGetResponse((IAsyncResult res) =>
        {
            WebResponse resp = ((HttpWebRequest)res.AsyncState).EndGetResponse(res);

            StreamReader respReader = new StreamReader(resp.GetResponseStream());
            respString = respReader.ReadToEnd();
            resp.Close();
            resp = null;
        }, hr);

        while (!hr.HaveResponse)
        {
            Console.Write("hiya bob!");
            Thread.Sleep(150);
        }

        Console.Write(respString);
        hr = null;

如何将上传的进度日志合并到一个日志中?任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

一个选项是计算在完成任何工作之前需要发送的总字节数:

// Calculate the total size to upload before starting work
long totalToUpload = 0;
foreach (var f in files)
{
    totalToUpload += (new FileInfo(f)).Length;
}

然后跟踪任何文件中发送的总字节数,并在计算进度时使用它:

int count = 0;
long bytesSoFar = 0;

foreach (string f in files)
{
    // ... Your existing work ...

    while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
    {
        bytesSoFar += bytesRead;
        // Make sure to only write the number of bytes read from the file
        s.Write(buffer, 0, bytesRead);
        // Console.WriteLine takes a string.Format() style string
        Console.WriteLine("sending file data {0:0.000}%", (bytesSoFar * 100.0f) / totalToUpload);
    }