2020年7月

简介

实时显示上传进度,参数可以根据自己需要来进行修改,可以封装为单独的上传函数

代码分为四个部分:上传部分、调用部分、实时进度部分、上传完成部分

核心代码

        /// <summary>
        /// 将本地文件上传到指定的服务器(HttpWebRequest方法)  
        /// </summary>
        /// <param name="url"></param>
        /// <param name="values"></param>
        /// <param name="filePath"></param>
        /// <param name="progress"></param>
        /// <param name="completed"></param>
        public static void UploadFile(string url, NameValueCollection values, string filePath, Action<string, int> progress, Action<string> completed)
        {
            var fileStream = File.OpenRead(filePath);
            var fileName = Path.GetFileName(filePath);
            var ms = new MemoryStream();
            // Make a copy of the input stream in case sb uses disposable stream
            fileStream.CopyTo(ms);
            // Stream position needs to be set to zero - just to be sure.
            ms.Position = 0;

            try
            {
                const string contentType = "application/octet-stream";

                var request = WebRequest.Create(url);
                request.Method = "POST";
                request.Headers.Add("Authorization", GlobalConfig.token);
                request.Headers.Add("source", "pc");

                var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
                request.ContentType = "multipart/form-data; boundary=" + boundary;
                boundary = "--" + boundary;

                var dataStream = new MemoryStream();
                byte[] buffer;
                // Write the values
                foreach (string name in values.Keys)
                {
                    buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
                    dataStream.Write(buffer, 0, buffer.Length);
                    buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
                    dataStream.Write(buffer, 0, buffer.Length);
                    buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
                    dataStream.Write(buffer, 0, buffer.Length);
                }

                // Write the file
                buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
                dataStream.Write(buffer, 0, buffer.Length);
                buffer = Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"file\"; filename=\"{fileName}\"{Environment.NewLine}");
                dataStream.Write(buffer, 0, buffer.Length);
                buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", contentType, Environment.NewLine));
                dataStream.Write(buffer, 0, buffer.Length);
                ms.CopyTo(dataStream);
                buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
                dataStream.Write(buffer, 0, buffer.Length);

                buffer = Encoding.ASCII.GetBytes(boundary + "--");
                dataStream.Write(buffer, 0, buffer.Length);


                dataStream.Position = 0;
                // Important part: set content length to directly write to network socket
                request.ContentLength = dataStream.Length;
                var requestStream = request.GetRequestStream();

                // Write data in chunks and report progress
                var size = dataStream.Length;
                const int chunkSize = 64 * 1024;
                buffer = new byte[chunkSize];
                long bytesSent = 0;
                int readBytes;
                while ((readBytes = dataStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    requestStream.Write(buffer, 0, readBytes);
                    bytesSent += readBytes;

                    var status = "Uploading... " + bytesSent / 1024 + "KB of " + size / 1024 + "KB";
                    var percentage = Convert.ToInt32(100 * bytesSent / size);
                    progress(status, percentage);
                }

                // Get response from host
                using (var response = request.GetResponse())
                using (var responseStream = response.GetResponseStream())
                using (var stream = new MemoryStream())
                {
                    responseStream.CopyTo(stream);
                    var result = Encoding.UTF8.GetString(stream.ToArray());
                    //completed(result == string.Empty
                    //    ? "failed:" + result
                    //    : "ok:" + result);
                    completed(result);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

调用

                    FrmUtil.UploadFile(
                        url: url,
                        filePath: path,
                        values: new NameValueCollection(),
                        progress: (status, percent) => UploadProgress(status, percent),
                        completed: UploadCompleted
                    );

回调

可实时实时进度显示

        /// <summary>
        /// 上传进度
        /// </summary>
        /// <param name="status"></param>
        /// <param name="percent"></param>
        private void UploadProgress(string status, int percent)
        {
            lab_upload.Text = percent + "%";
        }

上传完成

        /// <summary>
        /// 上传完成
        /// </summary>
        /// <param name="response"></param>
        private void UploadCompleted(string response)
        {
            var apiRes = JsonConvert.DeserializeObject<ApiResultEntity<List<string>>>(response);
            var apiRet = apiRes.ToReturn();
            if (apiRet.res)
            {
                var url = apiRet.Data[0];

                // 发送socket
                var u = UserEntity.userInfo;
                string recImUserID = friendData.userId.ToString();
                string fileName = skinPictureBox3.Tag.ToString().GetFileName();
                string size = skinPictureBox3.Tag.ToString().GetFileSize() + "MB";
                FriendSendSocket.SendFriendFileMsg(
                    u.name,
                    u.imUserId,
                    u.imgPath,
                    recImUserID,
                    new MsgFileEntity()
                    {
                        fileName = fileName,
                        size = size,
                        url = url
                    }, UserEntity.userInfo.name, UserEntity.userInfo.imgPath);
            }
            else
            {
                MessageBox.Show($"发送失败:{apiRet.msg}");
            }

            lab_upload.Visible = false;
            lab_upload.Text = "00.00%";
        }