天道酬勤

博观而约取,厚积而薄发!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Silverlight中用WCF实现文件快速上传(二、改进)

Posted on 2010-07-15 11:36  Happy Coding  阅读(579)  评论(0编辑  收藏  举报

   上一篇中提到Silverlight + WCF实现文件上传的一个缺点:一次性的将文件读到内存。显然,当文件的尺寸大到内存难以容纳时,这种方法是有问题的。

 处理这个问题时,自然的会想到,可以边读边上传。实测的情况,该方法实现也很简单,下面简要描述一下。

    1. 创建解决方案的方法和修改配置的方法同“Silverlight中用WCF实现文件快速上传(一)”,不再赘述。

    2. Silverlight中的实现

    辅助类:

    public class UserFile
    {

        public string Name { get; set; }  //文件名
        public long Length { get; set; }  //文件长度
        public int BytesRead { get; set; }  //本次读到的字节数
        public long BytesSent { get; set; }  //已经发送(上传)的字节数
        public System.IO.FileStream FileStream { get; set; }  //文件流
    }

    MainPage.cs中的实现:

    public partial class MainPage : UserControl
    {
        private const int BUFFER_SIZE = 2097152;  //2MB
        private UserFile _file;
        private byte[] _buffer;
        private localService.Service1Client _client;

        public MainPage()
        {
            btnUploadFile.Click += new RoutedEventHandler(Button_Click);

            _buffer = new byte[BUFFER_SIZE];
            _client = new localService.Service1Client();
            //事件处理

            _client.ActionUploadCompleted += newEventHandler<System.ComponentModel.AsyncCompletedEventArgs>(_client_ActionUploadCompleted);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //选择本地文件对话框
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "(*.*)|*.*";
            //单选
            openFileDialog.Multiselect = false;

            if (openFileDialog.ShowDialog() == true)
            {
                _file = new UserFile();
                FileInfo fileInfo = openFileDialog.File;
                _file.Name = fileInfo.Name;
                _file.Length = fileInfo.Length;
                _file.BytesRead = 0;
                _file.BytesSent = 0;
                _file.FileStream = fileInfo.OpenRead();

                //初始化进度条

                prgUpload.Minimum = 0;
                prgUpload.Maximum = Math.Ceiling((double)_file.Length / (double)_buffer.Length);

                int bytesRead = _file.FileStream.Read(_buffer, 0, _buffer.Length);
                if (bytesRead > 0)
                {
                    _file.BytesRead = bytesRead;

                    _client.ActionUploadAsync(_file.Name, _buffer, false);
                }
                else
                {
                    _file.FileStream.Close();
                }
            }
        }

        void _client_ActionUploadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                _file.BytesSent += _file.BytesRead;

                prgUpload.Value = Math.Ceiling((double)_file.BytesSent / (double)_buffer.Length);  //更新进度条

                if (_file.BytesSent < _file.Length)
                {
                    int bytesRead = _file.FileStream.Read(_buffer, 0, _buffer.Length);
                    if (bytesRead > 0)
                    {
                        _file.BytesRead = bytesRead;
                        _client.ActionUploadAsync(_file.Name, _buffer, true);
                    }
                    else
                    {
                        _file.FileStream.Close();
                    }
                }
                else
                {
                    _file.FileStream.Close();
                }
            }
        }

    }

    3. 总结

    本方法实现了边读文件边上传,实测时可以快速上传任意大小的文件。另外,还增加了上传的进度条。