Silverlight之文件上傳組件


摘要:

文件上傳是日常開過程中最常用的功能之一,目前實現文件上傳的方式多種多樣。這其中較為復雜的情況就是關於大文件、多文件上傳的問題,目前解決大文件、多文件上傳一般借助於js或者flash組件,今天就同大家一起看一下如何使用silverlight實現這個功能,而且功能和用戶體驗相對會更好一些。

主要內容:

一、組件特點

二、實現原理

三、編碼實現

一、組件特點

對於今天要說的組件姑且叫做"CmjUpload"吧,方便稱呼。目前有很多上傳組件來輔助完成日常開發,"CmjUpload"有什么特點呢:

  1. 解決大文件、多文件上傳問題
  2. 基於asp.net上傳,不需要部署WCF、WebService操作方便
  3. 接口豐富、靈活性強,配置使用方便。
  4. 支持選擇、拖拽兩種文件添加方式上傳,用戶體驗好。
  5. 支持取消、暫停、繼續操作滿足續傳要求。

OK,就說那么多吧,主要是讓大家有興趣看下去,其實之所以有今天的話題主要還是為了學習以及滿足實際開發需求。

二、實現原理

在Silverlight中要實現上傳有很多方式,例如說使用WCF或者WebService,但是考慮到實際情況,這里沒有選擇以上兩種方式,而是選擇了WebRequest方式。原因比較簡單,部署十分方便,不需要為了上傳組件而進行額外的配置。Silverlight中使用WebRequest同其他.Net開發中的使用方式是類似的,不同的是Silverlight中很多操作都是異步的,當然WebRequest也不例外。此外,在這里需要對一個文件分塊發送,一方面可以解決大文件上傳問題,另一方面可以實時顯示文件上傳進度。下面一個簡單的交互過程:

 analysisDesgin

當然要完成整個組件遠不止上面說的這些,UI的設計,組件的本地化,用戶接口的設計等都是必須思考的問題。下面是組件界面原型:

mockup

界面分為兩個區域:文件顯示區域和操作區域,當然這里的文件區域本身也是可以操作的,例如如果你不想點擊按鈕選擇文件的話,可以選擇直接拖拽一個或多個文件到文件區域。還可以對已添加的文件進行刪除操作,對正在上傳的文件進行暫停和續傳操作。此外文件區域的設計主要提供文件信息顯示,例如縮略圖、上傳進度、文件名稱、文件大小等信息。操作區域一方面提供文件整體信息的顯示(例如文件總數、已上傳數等),另一方面提供了文件瀏覽、上傳、清空操作。

下面是類的設計:

classDesgin

在上圖中我們可以看出有三個包:Core、Config、Util。

Core是核心包,里面主要包括文件隊列管理(FileQueue)、文件上傳控制(FileUpload)、文件界面區域(FileArea)、文件大小單位轉換(FileSize)、縮略圖控制(FileIcon)。

Config是配置和接口包,主要包括組件設計級別常量(注意不是用戶級別也不是開發級別,開發級別配置在接口中進行)(UploadConstant)、客戶端開發接口(ExposeInterface)、本地化實現(Localization)、接口注冊(ClientInteraction)。

Util包主要包括一些常用輔助類,主要包括xml操作(XmlHelper)、服務器端文件保存輔助類(CmjUpload)。

三、編碼實現

有了上面的分析相信下面的實現就相當容易理解了,首先看一下文件上傳類FileUpload:

 

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using System.IO;
using System.Windows.Threading;
using CmjUpload.Util;
using CmjUpload.Config;

namespace CmjUpload
{
    public class FileUpload
    {
        //開始上傳
        public delegate void StartUploadHanler(object sender,EventArgs e);
        public event StartUploadHanler StartUpload;
        public void OnStartUpload(object sender, EventArgs e)
        {
            if (StartUpload != null)
            {
                StartUpload(sender, e);
            }
        }

        // 上傳
        public delegate void UploadingHanler(object sender, ProgressArgs e);
        public event UploadingHanler Uploading;
        public void OnUploading(object sender, ProgressArgs e)
        {
            if (Uploading != null)
            {
                Uploading(sender,e);
            }
        }

        //上傳結束
        public delegate void UploadCompletedHanler(object sender, EventArgs e);
        public event UploadCompletedHanler UploadCompleted;
        public void OnUploadCompleted(object sender, EventArgs e)
        {
            if (UploadCompleted != null)
            {
                UploadCompleted(sender, e);
            }
        }


        private string _requestUrl = "";
        private string _fileName = "";
        private long _fileLength = 0;
        private long _blockLength = 4096;//單次上傳文件大小
        private long _postedLength = 0;//已傳輸文件大小
        private long _nextLength = 0;//下次傳輸的文件大小
        private bool _firstUpload = true;
        private BinaryReader _fileReader = null;

        private UploadStatus _uploadStatus = UploadStatus.Start;

        public FileInfo File
        {
            get;
            set;
        }

        //public long PostedLength
        //{
        //    get
        //    {
        //        return _postedLength;
        //    }
        //    set
        //    {
        //        _postedLength = value;
        //    }
        //}

        public UploadStatus Status
        {
            get
            {
                return _uploadStatus;
            }
            set
            {
                _uploadStatus = value;
            }
        }

        public void Upload(FileInfo file)
        {
            this.File = file;
            //XmlHelper xmlHelper = new XmlHelper("Config/CmjUploadConfig.xml");
            //_requestUrl=xmlHelper.GetAttibuteValue("Upload", "RequestUrl");
            _requestUrl = ExposeInterface.Instance().RequestUrl;
            this._fileName = this.File.Name;
            this._fileLength = this.File.Length;
            this._blockLength = FileSize.GetLockSize(this._fileLength);
            //this._postedLength = 0;
            _fileReader = new BinaryReader(file.OpenRead());
            //_uploadStatus = UploadStatus.Start;
            if (_fileLength < _blockLength)
            {
                _nextLength = _fileLength;
            }
            else
            {
                _nextLength = _blockLength;
            }
            OnStartUpload(this, new EventArgs());

            UploadInBlock();
        }

        public void UploadInBlock()//上傳一塊數據
        {
            UriBuilder uriBuilder = new UriBuilder(new Uri(_requestUrl, UriKind.Absolute));
            uriBuilder.Query = string.Format("fileName={0}&status="+_uploadStatus,this._fileName);
            WebRequest request = WebRequest.Create(uriBuilder.Uri);
            request.Method = "POST";
            request.ContentType = "multipart/mixed";//注意這里
            request.ContentLength = _nextLength;
            if (_firstUpload)
            {
                _uploadStatus = UploadStatus.Uploading;
                _firstUpload = false;
            }
            request.BeginGetRequestStream((IAsyncResult asyncResult) =>
            {
                WebRequest rqst = asyncResult.AsyncState as WebRequest;
                Stream rqstStm = rqst.EndGetRequestStream(asyncResult);

                byte[] buffer = new byte[_blockLength];
    
                int size = _fileReader.Read(buffer, 0, buffer.Length);
                if(size>0)
                {
                    rqstStm.Write(buffer, 0, size);
                    rqstStm.Flush();
                    _postedLength += size;
                    if ((_fileLength - _postedLength) < _blockLength)
                    {
                        _nextLength = _fileLength-_postedLength;
                    }
                }
                rqstStm.Close();

                rqst.BeginGetResponse((IAsyncResult ascResult) =>//開始數據傳輸
                {
                    OnUploading(this, new ProgressArgs() { Percent = ((double)_postedLength / (double)_fileLength) });

                    WebRequest webRequest = ascResult.AsyncState as WebRequest;
                    WebResponse webResponse = (WebResponse)webRequest.EndGetResponse(ascResult);
                    StreamReader reader = new StreamReader(webResponse.GetResponseStream());
                    string responsestring = reader.ReadToEnd();
                    reader.Close();
                    if (_postedLength >= _fileLength)
                    {
                        _uploadStatus = UploadStatus.Complelte;
                    }
                    if (_uploadStatus == UploadStatus.Uploading)
                    {
                        UploadInBlock();
                    }
                    //else if(_uploadStatus==UploadStatus.Cancel)
                    //{
                    //    return;
                    //}
                    else if (_uploadStatus==UploadStatus.Complelte)
                    {
                        _fileReader.Close();
                        OnUploadCompleted(this, new EventArgs());
                    }
                }, request);
            }, request);
        }

        /// <summary>
        /// 繼續上傳
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="uploadedLength"></param>
        //public static void ContinueUplaod(string fileName,long uploadedLength)
        //{

        //}
    }

    //上傳進度參數
    public class ProgressArgs:EventArgs
    {
        public double Percent
        {
            get;
            set;
        }
    }

    public enum UploadStatus
    {
        Start,
        Uploading,
        Cancel,
        Complelte
    }
}

在這個類中需要注意的是狀態的控制,因為組件需要實現文件暫停、續傳功能,並且每次請求時需要發送相應的操作狀態;另一點就是對外公開了三個事件,用於給UI提供進度支持和狀態通知。

FileQueue管理整個文件隊列,控制着界面UI、文件上傳等信息:

 

using System;
using System.Collections.Generic;
using System.IO;

namespace CmjUpload
{
    /// <summary>
    /// 文件隊列管理者
    /// </summary>
    public class FileQueue
    {
        private static object _lock = new object();
        private static FileQueue _fileQueue = null;
        private Dictionary<string, int> _fileIndexs = null;//文件同索引對應關系
        private Dictionary<string,FileInfo> _files = null;
        private Dictionary<string,FileArea> _fileAeas = null;
        private Dictionary<string, FileUpload> _fileUploader = null;
        private int index = 0;

        private FileQueue()
        {
            _fileIndexs = new Dictionary<string, int>();
            _files = new Dictionary<string, FileInfo>();
            _fileAeas = new Dictionary<string, FileArea>();
            _fileUploader = new Dictionary<string, FileUpload>();
        }

        public static FileQueue Instance()
        {
            lock (_lock)
            {
                if (_fileQueue == null)
                {
                    _fileQueue = new FileQueue();
                }
            }
            return _fileQueue;
        }

        public void Add(FileInfo file)
        {
            _fileIndexs.Add(file.Name, index);
            _files.Add(file.Name,file);
            FileArea fileAerea = new FileArea(file);
            _fileAeas.Add(file.Name, fileAerea);
            ++index;
        }

        public void Remove(string fileName)
        {
            _fileIndexs.Remove(fileName);
            _files.Remove(fileName);
            _fileAeas.Remove(fileName);
            _fileUploader.Remove(fileName);
        }

        public Dictionary<string,FileInfo> Files
        {
            get
            {
                return _files;
            }
            set
            {
                _files = value;
            }
        }

        public Dictionary<string, FileArea> FileAreas
        {
            get
            {
                return _fileAeas;
            }
            set
            {
                _fileAeas = value;
            }
        }

        public Dictionary<string, FileUpload> FileUploader
        {
            get
            {
                return _fileUploader;
            }
            set
            {
                _fileUploader = value;
            }
        }

        public int GetFileIndex(string fileName)
        {
            int i=-1;
            if (_fileIndexs.ContainsKey(fileName))
            {
                i = _fileIndexs[fileName];
            }
            return i;
        }

        public void Clear()
        {
            string[] tempFileNames=new string[this.Files.Count];
            this.Files.Keys.CopyTo(tempFileNames,0);
            foreach (string fileName in tempFileNames)
            {
                this.Remove(fileName);
            }
        }
    }
}

FileArea用於構建每個文件的UI展示:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.IO;
using Cmj.MyWeb.MySilverlight.MyUserControl.Button;

namespace CmjUpload
{
    public class FileArea
    {
        private FileInfo _file = null;
        //private int _number = 0;
        private Grid _container = null;
        private TextBlock _name = null;
        private Image _thumnail = null;
        private ProgressBar _progress = null;
        private TextBlock _size = null;
        private TextBlock _percent = null;
        private Cancel _cancel = null;
        private Pause _pause = null;
        private Play _continue = null;
        private Check _complete = null;

        public FileArea(FileInfo file)
        {
            _file = file;
            //_number = number;
            _container = new Grid();
            _container.Name = "fileArea_container_" + file.Name;
            _container.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(60)});
            _container.ColumnDefinitions.Add(new ColumnDefinition());
            _container.ColumnDefinitions.Add(new ColumnDefinition() { Width=new GridLength(60)});
            _container.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(60) });
            _container.Height = 50;

            _thumnail = new Image();
            _thumnail.Name = "fileArea_thumnail_" + file.Name;
            _thumnail.Height = 40;
            _thumnail.Source = FileIcon.Instance().GetThumbnailImage(file);
            _thumnail.VerticalAlignment = VerticalAlignment.Bottom;
            _thumnail.HorizontalAlignment = HorizontalAlignment.Center;
            Grid.SetColumn(_thumnail, 0);
            
            _progress = new ProgressBar();
            _progress.Name = "fileArea_progress_" + file.Name;
            _progress.Minimum = 0;
            _progress.Maximum = 100;
            _progress.Value = 0;
            _progress.Height = 20;
            _progress.VerticalAlignment = VerticalAlignment.Bottom;
            //_progress.HorizontalAlignment = HorizontalAlignment.Center;
            Grid.SetColumn(_progress, 1);

            _name = new TextBlock();
            _name.Name = "fileArea_name_" + file.Name;
            _name.Text = file.Name;
            _name.VerticalAlignment = VerticalAlignment.Bottom;
            _name.HorizontalAlignment = HorizontalAlignment.Left;
            _name.Margin = new Thickness(10, 0, 0, 2);
            Grid.SetColumn(_name, 1);

            _percent = new TextBlock();
            _percent.Name = "fileArea_percent_" + file.Name;
            _percent.VerticalAlignment = VerticalAlignment.Bottom;
            _percent.HorizontalAlignment = HorizontalAlignment.Right;
            _percent.Margin = new Thickness(0, 0, 10, 2);
            Grid.SetColumn(_percent, 1);

            _size = new TextBlock();
            _size.Name = "fileArea_size_" + file.Name;
            _size.VerticalAlignment = VerticalAlignment.Bottom;
            _size.HorizontalAlignment = HorizontalAlignment.Right;
            Grid.SetColumn(_size, 2);

            _cancel = new Cancel();
            _cancel.Name = "fileArea_cancel_"+file.Name;
            _cancel.Width = 15;
            _cancel.Height = 15;
            _cancel.VerticalAlignment = VerticalAlignment.Bottom;
            //_cancel.Click += new RoutedEventHandler(_cancel_Click);
            Grid.SetColumn(_cancel, 3);
            _pause = new Pause();
            _pause.Name = "fileArea_pause_" + file.Name;
            _pause.Width = 15;
            _pause.Height = 15;
            _pause.VerticalAlignment = VerticalAlignment.Bottom;
            _pause.Visibility = Visibility.Collapsed;
            Grid.SetColumn(_pause, 3);
            _continue = new Play();
            _continue.Name = "fileArea_continue_" + file.Name;
            _continue.Width = 15;
            _continue.Height = 15;
            _continue.VerticalAlignment = VerticalAlignment.Bottom;
            _continue.Visibility = Visibility.Collapsed;
            Grid.SetColumn(_continue, 3);
            _complete = new Check();
            _complete.Name = "fileArea_complete_" + file.Name;
            _complete.Width = 18;
            _complete.Height = 18;
            _complete.VerticalAlignment = VerticalAlignment.Bottom;
            _complete.Visibility = Visibility.Collapsed;
            Grid.SetColumn(_complete, 3);

            _container.Children.Add(_thumnail);
            _container.Children.Add(_progress);
            _container.Children.Add(_size);
            _container.Children.Add(_name);
            _container.Children.Add(_percent);
            _container.Children.Add(_cancel);
            _container.Children.Add(_pause);
            _container.Children.Add(_continue);
            _container.Children.Add(_complete);

        }
        public Grid Container
        {
            get
            {
                return _container;
            }
            set
            {
                _container = value;
            }
        }

        public TextBlock Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }

        public Image Thumnail
        {
            get
            {
                return _thumnail;
            }
            set
            {
                _thumnail = value;
            }
        }

        public ProgressBar Progress
        {
            get
            {
                return _progress;
            }
            set
            {
                _progress = value;
            }
        }

        public TextBlock Size
        {
            get
            {
                return _size;
            }
            set
            {
                _size = value;
            }
        }

        public TextBlock Percent
        {
            get
            {
                return _percent;
            }
            set
            {
                _percent = value;
            }
        }

        public Cancel Cancel
        {
            get
            {
                return _cancel;
            }
            set
            {
                _cancel = value;
            }
        }

        public Pause Pause
        {
            get
            {
                return _pause;
            }
            set
            {
                _pause = value;
            }
        }

        public Play Continue
        {
            get
            {
                return _continue;
            }
            set
            {
                _continue = value;
            }
        }

        public Check Complete
        {
            get
            {
                return _complete;
            }
            set
            {
                _complete = value;
            }
        }
    }
}

ExposeInterface用於向客戶端調用提供操作接口:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Windows.Browser;

namespace CmjUpload.Config
{
    public class ExposeInterface
    {
        private static object _lock = new object();
        private static ExposeInterface _exposeInterface = null;

        private string _fileTypes = string.Empty;
        private string _fileDialogFilter = string.Empty;
        private long _limitSize = 0;
        private int _limitCount = 0;

        private ExposeInterface()
        {
        }

        public static ExposeInterface Instance()
        {
            lock (_lock)
            {
                if (_exposeInterface == null)
                {
                    _exposeInterface = new ExposeInterface();
                }
            }
            return _exposeInterface;
        }

        [ScriptableMember]
        public string FileTypes //ex:*.jpg|*.gif
        {
            get
            {
                return _fileTypes;
            }
            set
            {
                _fileTypes = value;
            }
        }

        [ScriptableMember]
        public string FileDialogFilter
        {
            get
            {
                if (this._fileDialogFilter == string.Empty&&this._fileTypes!=string.Empty)
                {
                    string[] types = this._fileTypes.Split('|');
                    string[] filters=new string[types.Length];
                    for(int i=0;i<types.Length;++i)
                    {
                        filters[i] = "("+types[i] +")|"+ types[i];
                    }
                    _fileDialogFilter = string.Join("|",filters);
                }
                return _fileDialogFilter;
            }
            set
            {
                _fileDialogFilter = value;
            }
        }

        [ScriptableMember]
        public long LimitSize//單位 MB
        {
            get
            {
                return _limitSize;
            }
            set
            {
                _limitSize = value;
            }
        }

        [ScriptableMember]
        public int LimitCount
        {
            get
            {
                return _limitCount;
            }
            set
            {
                _limitCount = value;
            }
        }

        [ScriptableMember]
        public string RequestUrl
        {
            get;
            set;
        }

        public List<string> GetFileExtensions()
        {
            List<string> extensions = new List<string>();
            string[] types = this._fileTypes.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            foreach(string type in types)
            {
                extensions.Add(type.TrimStart('*'));
            }
            return extensions;
        }
    }
}

CmjUpload用於提供給服務器端進行文件操作,服務端只需要簡單調用其Save方法就可以進行文件保存:

using System;
using System.Collections.Generic;
using System.Web;
using System.IO;

namespace CmjUpload.Web.Util
{
    public class CmjUpload
    {
        public static void Save(string relationPath)
        {
            string fileName = HttpContext.Current.Request["fileName"];
            Save(relationPath,fileName);
        }

        public static void Save(string relationPath,string outputName)
        {
            string status = HttpContext.Current.Request["status"];
            if (status == "Start")
            {
                using (FileStream fs = File.Create(Path.Combine(relationPath, outputName)))
                {
                    SaveFile(HttpContext.Current.Request.InputStream, fs);
                }
            }
            else if (status == "Uploading")
            {
                using (FileStream fs = File.Open(Path.Combine(relationPath, outputName), FileMode.Append))
                {
                    SaveFile(HttpContext.Current.Request.InputStream, fs);
                }
            }
            else if (status == "Completed")
            {
                HttpContext.Current.Response.Write("{success:true}");
            }
        }

        private static void SaveFile(Stream stream, FileStream fs)
        {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
            {
                fs.Write(buffer, 0, bytesRead);
            }
        }
    }
}

OK,其他的代碼就不再貼出了,看一下客戶端如何使用吧。

為了方便使用客戶端提供一個公用js類CmjUpload.js:

//注意要在控件加載完之后調用,建議放到插件onload事件中初始化(<param name="onLoad" value="pluginLoaded" />)
var CmjUpload = function (options) {
    var uploader = null; 
    if (options.hasOwnProperty("id")) {//組件id
        uploader = document.getElementById(options.id);
    } else {
        alert("Please configure the id attribute before use CmjUpload component!");
        return;
    }

    if (options.hasOwnProperty("requestUrl")) {//請求的url
        uploader.content.cmjUpload.RequestUrl = options.requestUrl;
    } else {
        alert("Please configure the requestUrl attribute before use CmjUpload component!");
        return;
    }

    if (options.hasOwnProperty("fileTypes")) {//文件類型限制
        uploader.content.cmjUpload.FileTypes = options.fileTypes;
    }
    if (options.hasOwnProperty("limitCount")) {//每批次上傳的文件數
        uploader.content.cmjUpload.LimitCount = options.limitCount;
    }
    if (options.hasOwnProperty("limitSize")) {//單個文件大小限制
        uploader.content.cmjUpload.LimitSize = options.limitSize;
    }
}
CmjUpload.prototype.onBeforeFileUpload = function () {//單個文件上傳之前執行
    
}

CmjUpload.prototype.onFileUploading = function () { //單個文件上傳時執行
    
}

CmjUpload.prototype.onFileUploaded = function () {//單個文件上傳完畢執行

}

CmjUpload.prototype.onBatchUploaded = function () {//整個批次的文件上傳完畢執行

}

然后在頁面添加上傳組件(本地化語言在param中進行配置):

<object id="cmjUpload1" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
	<param name="source" value="ClientBin/CmjUpload.xap"/>
	<param name="onError" value="onSilverlightError" />
    <param name="onLoad" value="pluginLoaded" /><!--注意這里,必須保證配置信息在頁面加載之后執行-->
    <param name="culture" value="en-US" /><!--注意這里本地化配置-->
    <param name="uiculture" value="en-US" /><!--注意這里本地化配置-->
	<param name="background" value="white" />
	<param name="minRuntimeVersion" value="4.0.50826.0" />
	<param name="autoUpgrade" value="true" />
	<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
 		<img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
	</a>
</object>

使用時在頁面引用該類,進行id和url等信息配置,具體的配置內容上面js已經注釋的很清楚,這里不再贅余。例如對頁面做如下配置:

pluginLoaded=function(){
    var upload = new CmjUpload({ id: 'cmjUpload1', requestUrl: 'http://localhost:3407/Upload.aspx', fileTypes: '*.jpg|*.png|*.wmv|*.rar|*.iso', limitCount: 5, limitSize: 150 });
}

后台文件執行文件保存操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

namespace CmjUpload.Web
{
    public partial class Upload : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            CmjUpload.Web.Util.CmjUpload.Save("f:\\");
        }
    }
}

下面是使用效果:

類型限制

fileTypeLimit

大小限制

fileSizeLimit

數量限制

fileCountLimit

刪除一個文件

fileDelete

上傳中

uploading

上傳暫停

uploadPause

完成上傳

uploadComplete

手動清空(即使不手動清空繼續上傳文件會自動清空,清空操作主要用於上傳暫停后不需要上傳的清空)

uploadClear

下面看看本地化設置為英文后的效果

englishUI

我們通過修改LimitCount來看一下大文件傳輸,好幾個G的文件同時傳輸也沒有問題

 bigFileUpload

OK,最后附上組件下載,使用方法上面說的也比較清楚了。關於組件源代碼就不再提供下載了,相信讀完這篇文章要實現並不難,真正需要的話可以給我留言或發郵件KenshinCui@hotmail.com

組件下載download


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM