开发者社区> 问答> 正文

.net文件上传进度的实现

先说一下原理

在阿里云 net.sdk 中 关于上传文件有这样的示例:
OssClient ossClient = new OssClient(accessId, accessKey);

using(var fs = File.Open(fileToUpload, FileMode.Open))

{

      ossClient.PutObject(bucketName, key, fs, metadata);

}


这是上传一个文件,文件大小小于5G。
其中 fs 可以替换成Stream ,这样就可以读取到上传的进度了
private Stream fs;

private void bgw_DoWork(object sender, DoWorkEventArgs e)

{

    fs = File.Open(FileToUpload, FileMode.Open);

    ObjectMetadata metadata = new ObjectMetadata();

    ClientConfiguration config = new ClientConfiguration();

    config.ConnectionTimeout = 3600 * 1000;  // 这里必须设置一下,不然会超时导致上传失败,在上论坛找到的

    OssClient ossClient = new OssClient(new Uri(AliyunHelper.SDK.OSSUrl), AccessID, AccessKey, config);

    PutObjectResult Result = ossClient.PutObject(Bucket, Key, fs, metadata);

}

然后 需要读取上传进度的时候 计算一下就可以了
/// <summary>
        /// 计算上传速度和进度
        /// </summary>
        public void GetSpeed()
        {
            if (UploadFilish)
            {
                NeedTime = new TimeSpan(0, 0, 0);
                Speed = 0;
                Process = 100;
                return;
            }
            try
            {
                long Position = 0;
                if (fs != null)
                {
                    Position = fs.Position;
                }
                long UploadNum = Position - UploadSize;//两次之间的差值
                Speed = (int)(UploadNum / 1024);// KB/s
                UploadSize = Position;//更新所在位置
                if (FileSize > 0)
                {
                    Process = (int)(UploadSize * 100 / FileSize);//计算进度 %
                }

                long LastSize = FileSize - UploadSize;
                int UseTime = 0;
                if (Speed > 0)
                {
                    UseTime = (int)(LastSize / 1024 / Speed);//需要多少秒
                }
                NeedTime = new TimeSpan(0, 0, UseTime);
            }
            catch
            { }

            if (UploadFilish)
            {
                NeedTime = new TimeSpan(0, 0, 0);
                Speed = 0;
                Process = 100;
            }

        }

具体的 可以在界面上拖一个Timer控件,间隔设为1秒
private void timerUpload_Tick(object sender, EventArgs e)
        {
            int Total = 0;
            int Num = 0;
            foreach (DataGridViewRow row in dataUpload.Rows)
            {
                string State = row.Cells["State"].Value.ToString();

                if (State == "等待上传")
                {
                    Num  ;
                    string FileToUpload = row.Cells["FileName"].Value.ToString();
                    foreach (var item in ListUpload)
                    {
                        if (item.FileToUpload == FileToUpload)
                        {
                            row.Cells["State"].Value = item.State;
                        }
                    }
                }
                else if (State == "正在上传")
                {
                    Num  ;
                    string FileToUpload = row.Cells["FileName"].Value.ToString();
                    foreach (var item in ListUpload)
                    {
                        if (item.FileToUpload == FileToUpload)
                        {

                            if (item.UploadFilish)
                            {
                                row.Cells["State"].Value = item.State;
                                row.Cells["Process"].Value = 100;
                                row.Cells["Speed"].Value = 0;
                                row.Cells["NeedTime"].Value = "00:00:00";

                            }
                            else
                            {
                                item.GetSpeed();//在这里 调用计算,下面紧接着就是 显示计算结果
                                row.Cells["Process"].Value = item.Process;
                                int Speed = item.Speed;
                                Total  = Speed;
                                row.Cells["Speed"].Value = Speed.ToString();
                                row.Cells["NeedTime"].Value = item.NeedTime.ToString();
                            }
                        }
                    }
                }
                else
                {

                }
            }

            lblUploadWaiteNum.Text = Num.ToString();
            lblSpeedTotal.Text = Total.ToString();
        }


最后 附上完整的类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aliyun.OpenServices.OpenStorageService;
using System.IO;
using System.ComponentModel;
using System.Timers;
using System.Threading;
using Aliyun.OpenServices;
using System.Security.Policy;
namespace ChangDu.AliyunHelper
{
    public class Upload
    {
        /// <summary>
        /// 要上传的文件=Folder "\\" Key
        /// </summary>
        /// <param name="AccessID"></param>
        /// <param name="AccessKey"></param>
        /// <param name="Bucket"></param>
        /// <param name="Key"></param>
        /// <param name="Folder"></param>
        public Upload(string AccessID, string AccessKey, string Bucket, string Key, string Folder)
        {
            this.AccessID = AccessID;
            this.AccessKey = AccessKey;
            this.Bucket = Bucket;
            this.Key = Key;
            this.FileToUpload = Folder   "\\"   Key;
            this.FileToMove = Folder   "\\Upload\\"   Key;
            FileSize = new FileInfo(FileToUpload).Length;
            UploadFilish = false;
            UploadOK = false;
            UploadSize = 0;
            Process = 0;
            Speed = 0;
            UploadStart = false;
            Started = false;
            State = "等待上传";
        }

        public string AccessID { get; set; }
        public string AccessKey { get; set; }
        public string Bucket { get; set; }
        /// <summary>
        /// 保存到OSS的KEY
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 要上传的文件的本地路径
        /// </summary>
        public string FileToUpload { get; set; }
        private string FileToMove { get; set; }
        /// <summary>
        /// 上传进度 百分比
        /// </summary>
        public int Process { get; set; }
        /// <summary>
        /// 上传速度 KB/s
        /// </summary>
        public int Speed { get; set; }
        public TimeSpan NeedTime { get; set; }
        /// <summary>
        /// 是否已经开始上传
        /// </summary>
        public bool UploadStart { get; set; }
        public bool Started { get; set; }
        /// <summary>
        /// 上传是否已经完成
        /// </summary>
        public bool UploadFilish { get; set; }
        /// <summary>
        /// 上传结果 是否成功
        /// </summary>
        public bool UploadOK { get; set; }
        private Stream fs;
        private string MD5 = "";
        /// <summary>
        /// 要上传的文件大小
        /// </summary>
        public long FileSize = 0;
        private long UploadSize = 0;
        private string _State = "";

        /// <summary>
        /// 上传状态
        /// </summary>
        public string State
        {

            get
            {
                lock (this)
                {
                    return _State;
                }
            }
            set
            {
                lock (this)
                {
                    _State = value;
                }
            }

        }

        /// <summary>
        /// 正式开始上传
        /// </summary>
        public void StartUpload()
        {
            Started = true;
            State = "正在上传";
            BackgroundWorker bgw = new BackgroundWorker();
            bgw.DoWork  = bgw_DoWork;
            bgw.RunWorkerCompleted  = bgw_RunWorkerCompleted;
            bgw.RunWorkerAsync();
        }
        /// <summary>
        /// 计算上传速度和进度
        /// </summary>
        public void GetSpeed()
        {
            if (UploadFilish)
            {
                NeedTime = new TimeSpan(0, 0, 0);
                Speed = 0;
                Process = 100;
                return;
            }
            try
            {
                long Position = 0;
                if (fs != null)
                {
                    Position = fs.Position;
                }
                long UploadNum = Position - UploadSize;//两次之间的差值
                Speed = (int)(UploadNum / 1024);// KB/s
                UploadSize = Position;//更新所在位置
                if (FileSize > 0)
                {
                    Process = (int)(UploadSize * 100 / FileSize);//计算进度 %
                }

                long LastSize = FileSize - UploadSize;
                int UseTime = 0;
                if (Speed > 0)
                {
                    UseTime = (int)(LastSize / 1024 / Speed);//需要多少秒
                }
                NeedTime = new TimeSpan(0, 0, UseTime);
            }
            catch
            { }

            if (UploadFilish)
            {
                NeedTime = new TimeSpan(0, 0, 0);
                Speed = 0;
                Process = 100;
            }

        }
        /// <summary>
        /// 上传结束
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                }
                UploadFilish = true;
            }
            catch
            { }
            finally
            {

            }
        }
        /// <summary>
        /// 上传中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                //申请许可证
                seamphore.WaitOne();
                UploadStart = true;
                MD5 = MD5Helper.GetMd5Hash(FileToUpload);
                fs = File.Open(FileToUpload, FileMode.Open);
                ObjectMetadata metadata = new ObjectMetadata();
                // 可以设定自定义的metadata。
                metadata.ContentType = "application/pdf";
                ClientConfiguration config = new ClientConfiguration();
                config.ConnectionTimeout = 3600 * 1000;  // 根据用户情况设置  (这里也可以设置成  -1   表示永不超时)
                OssClient ossClient = new OssClient(new Uri(AliyunHelper.SDK.OSSUrl), AccessID, AccessKey, config);

                PutObjectResult Result = ossClient.PutObject(Bucket, Key, fs, metadata);

                if (Result.ETag == MD5)
                {
                    //上传成功
                    UploadOK = true;
                    State = "上传成功";
                    try
                    {
                        if (File.Exists(FileToMove))
                        {
                            string Dir = Path.GetDirectoryName(FileToMove);
                            if (!Directory.Exists(Dir))
                            {
                                Directory.CreateDirectory(Dir);
                            }
                            File.Move(FileToUpload, FileToMove);
                        }
                    }
                    catch
                    { }
                }
                else
                {
                    UploadOK = false;
                    State = "上传失败";
                    SDK.DeleteObject(ossClient, Bucket, Key);
                }
            }
            catch (Exception ex)
            {
                //请求被中止: 请求已被取消
                UploadOK = false;
                State = "上传失败";
            }
            finally
            {
                //释放许可证  
                seamphore.Release();
            }
        }


        public static int MaxThreadNum = 3;
        public static Semaphore seamphore = new Semaphore(MaxThreadNum, MaxThreadNum);

        /// <summary>
        /// 设置 最大的同时上传线程数
        /// </summary>
        /// <param name="MaxNum"></param>
        public static void SetThreadNum(int MaxNum)
        {
            MaxThreadNum = MaxNum;
            seamphore = new Semaphore(MaxNum, MaxNum);
        }
    }
}

展开
收起
changdu3601 2013-03-13 22:19:10 18536 0
7 条回答
写回答
取消 提交回答
  • Renet文件上传进度的实现
    问题很好,但我这边测试遇到了问题,进程除了问题
    2015-08-21 11:06:07
    赞同 展开评论 打赏
  • 回楼主changdu3601的帖子
    请教下怎么判断是否上传成功?就那个什么MD5比较吧?我不太会写,能给段代码吗?官方的API各个版本的都看了也不会。
    2014-12-17 17:29:53
    赞同 展开评论 打赏
  • LT是个伪程序员
    支持~~~~
    2014-04-28 16:31:15
    赞同 展开评论 打赏
  • Renet文件上传进度的实现
      ClientConfiguration config = new ClientConfiguration();
        config.ConnectionTimeout = -1 ; // 这里必须设置一下,不然会超时导致上传失败,在上论坛找到的
        OssClient ossClient = new OssClient(new Uri(AliyunHelper.SDK.OSSUrl), AccessID, AccessKey, config);

    你好,我把   config.ConnectionTimeout = -1 ;30秒左右就会报无法访问已关闭的文件,请问这个是什么问题,如何解决。
    2014-03-17 10:12:09
    赞同 展开评论 打赏
  • Renet文件上传进度的实现
    这个必须顶

    -------------------------

    Renet文件上传进度的实现
    PutObjectResult Result = ossClient.PutObject(Bucket, Key, fs, metadata);  这个地方没有阻塞啊 ?一调就返回
    2014-03-10 10:18:40
    赞同 展开评论 打赏
  • Renet文件上传进度的实现
    好人啊,需要的就是这个啊!
    2014-03-07 10:18:23
    赞同 展开评论 打赏
  • Renet文件上传进度的实现
    沙发啊 http://www.sxlocky.com
    2013-03-15 16:37:22
    赞同 展开评论 打赏
滑动查看更多
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载