分析Silverlight文件上傳組件
文件上傳是日常開(kāi)過(guò)程中最常用的功能之一,目前實(shí)現(xiàn)文件上傳的方式多種多樣。這其中較為復(fù)雜的情況就是關(guān)于大文件、多文件上傳的問(wèn)題,目前解決大文件、多文件上傳一般借助于js或者flash組件,今天就同大家一起看一下如何使用silverlight實(shí)現(xiàn)這個(gè)功能,而且功能和用戶體驗(yàn)相對(duì)會(huì)更好一些。
主要內(nèi)容:
一、組件特點(diǎn)
二、實(shí)現(xiàn)原理
三、編碼實(shí)現(xiàn)
一、組件特點(diǎn)
對(duì)于今天要說(shuō)的組件姑且叫做"CmjUpload"吧,方便稱(chēng)呼。目前有很多上傳組件來(lái)輔助完成日常開(kāi)發(fā),"CmjUpload"有什么特點(diǎn)呢:
解決大文件、多文件上傳問(wèn)題
基于asp.net上傳,不需要部署WCF、WebService操作方便
接口豐富、靈活性強(qiáng),配置使用方便。
支持選擇、拖拽兩種文件添加方式上傳,用戶體驗(yàn)好。
支持取消、暫停、繼續(xù)操作滿足續(xù)傳要求。
OK,就說(shuō)那么多吧,主要是讓大家有興趣看下去,其實(shí)之所以有今天的話題主要還是為了學(xué)習(xí)以及滿足實(shí)際開(kāi)發(fā)需求。
二、實(shí)現(xiàn)原理
在Silverlight中要實(shí)現(xiàn)上傳有很多方式,例如說(shuō)使用WCF或者WebService,但是考慮到實(shí)際情況,這里沒(méi)有選擇以上兩種方式,而是選擇了WebRequest方式。原因比較簡(jiǎn)單,部署十分方便,不需要為了上傳組件而進(jìn)行額外的配置。Silverlight中使用WebRequest同其他.Net開(kāi)發(fā)中的使用方式是類(lèi)似的,不同的是Silverlight中很多操作都是異步的,當(dāng)然WebRequest也不例外。此外,在這里需要對(duì)一個(gè)文件分塊發(fā)送,一方面可以解決大文件上傳問(wèn)題,另一方面可以實(shí)時(shí)顯示文件上傳進(jìn)度。下面一個(gè)簡(jiǎn)單的交互過(guò)程:

當(dāng)然要完成整個(gè)組件遠(yuǎn)不止上面說(shuō)的這些,UI的設(shè)計(jì),組件的本地化,用戶接口的設(shè)計(jì)等都是必須思考的問(wèn)題。下面是組件界面原型:

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

在上圖中我們可以看出有三個(gè)包:Core、Config、Util。
Core是核心包,里面主要包括文件隊(duì)列管理(FileQueue)、文件上傳控制(FileUpload)、文件界面區(qū)域(FileArea)、文件大小單位轉(zhuǎn)換(FileSize)、縮略圖控制(FileIcon)。
Config是配置和接口包,主要包括組件設(shè)計(jì)級(jí)別常量(注意不是用戶級(jí)別也不是開(kāi)發(fā)級(jí)別,開(kāi)發(fā)級(jí)別配置在接口中進(jìn)行)(UploadConstant)、客戶端開(kāi)發(fā)接口(ExposeInterface)、本地化實(shí)現(xiàn)(Localization)、接口注冊(cè)(ClientInteraction)。
Util包主要包括一些常用輔助類(lèi),主要包括xml操作(XmlHelper)、服務(wù)器端文件保存輔助類(lèi)(CmjUpload)。
三、編碼實(shí)現(xiàn)
有了上面的分析相信下面的實(shí)現(xiàn)就相當(dāng)容易理解了,首先看一下文件上傳類(lèi)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
{
//開(kāi)始上傳
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);
}
}
//上傳結(jié)束
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;//下次傳輸?shù)奈募笮?/p>
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()//上傳一塊數(shù)據(jù)
{
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) =>//開(kāi)始數(shù)據(jù)傳輸
{
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>
/// 繼續(xù)上傳
/// </summary>
/// <param name="fileName"></param>
/// <param name="uploadedLength"></param>
//public static void ContinueUplaod(string fileName,long uploadedLength)
//{
//}
}
//上傳進(jìn)度參數(shù)
public class ProgressArgs:EventArgs
{
public double Percent
{
get;
set;
}
}
public enum UploadStatus
{
Start,
Uploading,
Cancel,
Complelte
}
}
在這個(gè)類(lèi)中需要注意的是狀態(tài)的控制,因?yàn)榻M件需要實(shí)現(xiàn)文件暫停、續(xù)傳功能,并且每次請(qǐng)求時(shí)需要發(fā)送相應(yīng)的操作狀態(tài);另一點(diǎn)就是對(duì)外公開(kāi)了三個(gè)事件,用于給UI提供進(jìn)度支持和狀態(tài)通知。
FileQueue管理整個(gè)文件隊(duì)列,控制著界面UI、文件上傳等信息:
using System;
using System.Collections.Generic;
using System.IO;
namespace CmjUpload
{
/// <summary>
/// 文件隊(duì)列管理者
/// </summary>
public class FileQueue
{
private static object _lock = new object();
private static FileQueue _fileQueue = null;
private Dictionary<string, int> _fileIndexs = null;//文件同索引對(duì)應(yīng)關(guān)系
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用于構(gòu)建每個(gè)文件的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用于向客戶端調(diào)用提供操作接口:
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用于提供給服務(wù)器端進(jìn)行文件操作,服務(wù)端只需要簡(jiǎn)單調(diào)用其Save方法就可以進(jìn)行文件保存:
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,其他的代碼就不再貼出了,看一下客戶端如何使用吧。
為了方便使用客戶端提供一個(gè)公用js類(lèi)CmjUpload.js:
//注意要在控件加載完之后調(diào)用,建議放到插件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")) {//請(qǐng)求的url
uploader.content.cmjUpload.RequestUrl = options.requestUrl;
} else {
alert("Please configure the requestUrl attribute before use CmjUpload component!");
return;
}
if (options.hasOwnProperty("fileTypes")) {//文件類(lèi)型限制
uploader.content.cmjUpload.FileTypes = options.fileTypes;
}
if (options.hasOwnProperty("limitCount")) {//每批次上傳的文件數(shù)
uploader.content.cmjUpload.LimitCount = options.limitCount;
}
if (options.hasOwnProperty("limitSize")) {//單個(gè)文件大小限制
uploader.content.cmjUpload.LimitSize = options.limitSize;
}
}
CmjUpload.prototype.onBeforeFileUpload = function () {//單個(gè)文件上傳之前執(zhí)行
}
CmjUpload.prototype.onFileUploading = function () { //單個(gè)文件上傳時(shí)執(zhí)行
}
CmjUpload.prototype.onFileUploaded = function () {//單個(gè)文件上傳完畢執(zhí)行
}
CmjUpload.prototype.onBatchUploaded = function () {//整個(gè)批次的文件上傳完畢執(zhí)行
}
然后在頁(yè)面添加上傳組件(本地化語(yǔ)言在param中進(jìn)行配置):
<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" /><!--注意這里,必須保證配置信息在頁(yè)面加載之后執(zhí)行-->
<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>
使用時(shí)在頁(yè)面引用該類(lèi),進(jìn)行id和url等信息配置,具體的配置內(nèi)容上面js已經(jīng)注釋的很清楚,這里不再贅余。例如對(duì)頁(yè)面做如下配置:
pluginLoaded=function(){
var upload = new CmjUpload({ id: 'cmjUpload1', requestUrl: 'http://localhost:3407/Upload.aspx', fileTypes: '*.jpg|*.png|*.wmv|*.rar|*.iso', limitCount: 5, limitSize: 150 });
}
后臺(tái)文件執(zhí)行文件保存操作:
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:\");
}
}
}
下面是使用效果:
類(lèi)型限制

大小限制

數(shù)量限制

刪除一個(gè)文件

上傳中

上傳暫停

完成上傳

手動(dòng)清空(即使不手動(dòng)清空繼續(xù)上傳文件會(huì)自動(dòng)清空,清空操作主要用于上傳暫停后不需要上傳的清空)

下面看看本地化設(shè)置為英文后的效果

我們通過(guò)修改LimitCount來(lái)看一下大文件傳輸,好幾個(gè)G的文件同時(shí)傳輸也沒(méi)有問(wèn)題

OK,***附上組件下載,使用方法上面說(shuō)的也比較清楚了。關(guān)于組件源代碼就不再提供下載了,相信讀完這篇文章要實(shí)現(xiàn)并不難,真正需要的話可以給我留言或發(fā)郵件KenshinCui@hotmail.com。
組件下載
本作品采用知識(shí)共享署名 2.5 中國(guó)大陸許可協(xié)議進(jìn)行許可,歡迎轉(zhuǎn)載,演繹或用于商業(yè)目的。但轉(zhuǎn)載請(qǐng)注明來(lái)自崔江濤(KenshinCui),并包含相關(guān)鏈接。
【編輯推薦】

















