411 lines
14 KiB
C#
411 lines
14 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Helper;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Web.Configuration;
|
||
using System.Web.UI;
|
||
using System.Web.UI.HtmlControls;
|
||
|
||
namespace Html5Uploader.Controls
|
||
{
|
||
[ParseChildren(true)]
|
||
[PersistChildren(false)]
|
||
[ToolboxData("<{0}:Html5UploaderClient runat=server></{0}:Html5UploaderClient>")]
|
||
public class Html5UploaderClient : Control, INamingContainer
|
||
{
|
||
Dictionary<SettingsNames, object> settings;
|
||
public Html5UploaderClient()
|
||
{
|
||
settings = new Dictionary<SettingsNames, object>();
|
||
RegisterScript = true;
|
||
}
|
||
private ITemplate _viewTemplate;
|
||
[DefaultValue("视图模板")]
|
||
[TemplateContainer(typeof(ViewTemplate))]
|
||
[PersistenceMode(PersistenceMode.InnerProperty)]
|
||
[Browsable(false)]
|
||
public ITemplate ViewTemplate
|
||
{
|
||
get { return _viewTemplate; }
|
||
set { _viewTemplate = value; }
|
||
}
|
||
[Description("客户端事件")]
|
||
[PersistenceMode(PersistenceMode.InnerProperty)]
|
||
public ClientEventsCollection ClientEvents
|
||
{ get; set; }
|
||
|
||
[Description("随文件一起提交的参数列表")]
|
||
[PersistenceMode(PersistenceMode.InnerProperty)]
|
||
public PostParametersCollection PostParameters
|
||
{ get; set; }
|
||
|
||
[Description("服务端处理程序")]
|
||
[UrlProperty]
|
||
public string Url
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.url) ? settings[SettingsNames.url] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.url] = value;
|
||
}
|
||
}
|
||
string _token;
|
||
public string Token {
|
||
get { return _token; }
|
||
set {
|
||
if (value == null || value.Length <= 50)
|
||
{ _token = value; }
|
||
else { throw new Exception("Token的长度不能超过50个字符。"); }
|
||
}
|
||
}
|
||
public string Placeholder
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.placeholder) ? settings[SettingsNames.placeholder] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.placeholder] = value;
|
||
}
|
||
}
|
||
public bool Multiple
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.multiple) ? (bool)settings[SettingsNames.multiple] : true;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.multiple] = value;
|
||
}
|
||
}
|
||
public string Accept
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.accept) ? settings[SettingsNames.accept] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.accept] = value;
|
||
}
|
||
}
|
||
public string Types
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.types) ? settings[SettingsNames.types] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.types] = value;
|
||
}
|
||
}
|
||
public string Timeout
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.timeout) ? settings[SettingsNames.timeout] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.timeout] = value;
|
||
}
|
||
}
|
||
public int MaxQueue
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.maxQueue) ? (int)settings[SettingsNames.maxQueue] : 2;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.maxQueue] = value;
|
||
}
|
||
}
|
||
public bool Dragable
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.dragable) ? (bool)settings[SettingsNames.dragable] : true;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.dragable] = value;
|
||
}
|
||
}
|
||
public string DragContainer
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.dragContainer) ? settings[SettingsNames.dragContainer] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.dragContainer] = value;
|
||
}
|
||
}
|
||
public string Progress
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.progress) ? settings[SettingsNames.progress] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.progress] = value;
|
||
}
|
||
}
|
||
public string BlobSize
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.blobSize) ? settings[SettingsNames.blobSize] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.blobSize] = value;
|
||
}
|
||
}
|
||
public UploaderSliceds Sliced
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.sliced) ? (UploaderSliceds)settings[SettingsNames.sliced] : UploaderSliceds.Auto;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.sliced] = value;
|
||
}
|
||
}
|
||
public string LimitSize
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.limitSize) ? settings[SettingsNames.limitSize] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.limitSize] = value;
|
||
}
|
||
}
|
||
public string ParseResult
|
||
{
|
||
get
|
||
{
|
||
return settings.ContainsKey(SettingsNames.parseResult) ? settings[SettingsNames.parseResult] as string : null;
|
||
}
|
||
set
|
||
{
|
||
settings[SettingsNames.parseResult] = value;
|
||
}
|
||
}
|
||
public bool RegisterScript { get; set; }
|
||
int ParseTimeout(string v)
|
||
{
|
||
string[] units = new string[] { "ms", "ss", "mm", "hh" };
|
||
Func<string, int> fn = u =>
|
||
{
|
||
for (int i = 0; i < units.Length; i++) { if (units[i] == u)return i; }
|
||
return 0;
|
||
};
|
||
Regex rgx = new Regex(@"^\s*(\d+)\s*(ms|(ss)|(mm)|(hh))?\s*$", RegexOptions.IgnoreCase);
|
||
var m = rgx.Match(v);
|
||
|
||
if (m == null || !m.Success)
|
||
{ throw new ArgumentException("“" + v + "”无效的表达式,如:二十四小时“24hh”的格式"); }
|
||
int time;
|
||
int.TryParse(m.Groups[1].Value, out time);
|
||
int index = fn(m.Groups[2].Success ? m.Groups[2].Value.ToLower() : "ss");
|
||
while (index-- > 0)
|
||
{
|
||
time *= (index == 1 ? 1000 : 60);
|
||
|
||
}
|
||
return time;
|
||
}
|
||
long ParseSize(string v)
|
||
{
|
||
string[] units = new string[] { "B", "KB", "MB", "GB", "TB" };
|
||
Func<string, int> fn = u =>
|
||
{
|
||
for (int i = 0; i < units.Length; i++) { if (units[i] == u)return i; }
|
||
return 0;
|
||
};
|
||
Regex rgx = new Regex(@"^\s*(\d+)\s*(B|(KB)|(MB)|(GB)|(TB))?\s*$", RegexOptions.IgnoreCase);
|
||
var m = rgx.Match(v);
|
||
|
||
if (m == null || !m.Success)
|
||
{ throw new ArgumentException("“"+v+"”无效的表达式,请参照“232MB”的格式"); }
|
||
long size;
|
||
long.TryParse(m.Groups[1].Value, out size);
|
||
int index = fn(m.Groups[2].Success ? m.Groups[2].Value.ToUpper() : "MB");
|
||
while (index-- > 0)
|
||
{
|
||
size *= 1024;
|
||
|
||
}
|
||
return size;
|
||
}
|
||
string ParseSetting(SettingsNames key,object v)
|
||
{
|
||
if (!settings.ContainsKey(key)) return null;
|
||
string s;
|
||
long size;
|
||
switch (key)
|
||
{
|
||
case SettingsNames.url:
|
||
s= v as string;
|
||
if (!string.IsNullOrWhiteSpace(s))
|
||
{ s = "\"" + ConvertHelper.ConvertToClientString(ResolveUrl(s)) + "\""; }
|
||
return s;
|
||
case SettingsNames.maxQueue:
|
||
return v == null ? null : v.ToString();
|
||
case SettingsNames.blobSize:
|
||
size = ParseSize(v as string);
|
||
long max=(((HttpRuntimeSection)WebConfigurationManager.OpenWebConfiguration("/").GetSection("system.web/httpRuntime")).MaxRequestLength-2)*1024;
|
||
return (size > max ? max : size).ToString();
|
||
case SettingsNames.limitSize:
|
||
size = ParseSize(v as string);
|
||
return size.ToString();
|
||
case SettingsNames.timeout:
|
||
return ParseTimeout(v as string).ToString();
|
||
case SettingsNames.dragable:
|
||
case SettingsNames.multiple:
|
||
return ((bool)v) ? "true" : "false";
|
||
case SettingsNames.sliced:
|
||
return ((UploaderSliceds)v) != UploaderSliceds.Auto ? ((UploaderSliceds)v).GetHashCode().ToString() : null;
|
||
case SettingsNames.dragContainer:
|
||
case SettingsNames.placeholder:
|
||
case SettingsNames.progress:
|
||
s = (v + "").Trim();
|
||
if (s.StartsWith("$:"))
|
||
{ s = s.Substring(2); }
|
||
else { s = "\"" + ConvertHelper.ConvertToClientString(s) + "\""; }
|
||
return s;
|
||
case SettingsNames.parseResult:
|
||
s = (v + "").Trim();
|
||
if (s.StartsWith("javascript:", StringComparison.CurrentCultureIgnoreCase))
|
||
{ s = "function(serverData){\n" + s.Substring(11) + "\n}"; }
|
||
return s;
|
||
default:
|
||
s= v as string;
|
||
if (!string.IsNullOrWhiteSpace(s))
|
||
{ s = "\"" + ConvertHelper.ConvertToClientString(s) + "\""; }
|
||
return s;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
protected override void OnInit(EventArgs e)
|
||
{
|
||
base.OnInit(e);
|
||
if (RegisterScript) { RegisterClientScript(); }
|
||
}
|
||
protected override void Render(HtmlTextWriter writer)
|
||
{
|
||
base.Render(writer);
|
||
Dictionary<string, object> AddedKey;
|
||
bool flag;
|
||
StringBuilder sb = new StringBuilder();
|
||
foreach (var s in settings)
|
||
{
|
||
string v = ParseSetting(s.Key, s.Value);
|
||
if (!string.IsNullOrWhiteSpace(v))
|
||
{ sb.AppendFormat("{0}{1}:{2}", sb.Length > 0 ? "," : null, s.Key, v); }
|
||
}
|
||
if (!string.IsNullOrWhiteSpace(_token))
|
||
{
|
||
if (PostParameters == null) { PostParameters = new PostParametersCollection(); }
|
||
PostParameters.Insert(0, new PostParameter("token", _token));
|
||
|
||
}
|
||
if (PostParameters != null && PostParameters.Count > 0)
|
||
{
|
||
AddedKey = new Dictionary<string, object>();
|
||
flag = false;
|
||
sb.AppendFormat("{0}params:{{", sb.Length > 0 ? "," : null);
|
||
foreach (var s in PostParameters)
|
||
{
|
||
AddedKey.Add(s.Key, null);
|
||
sb.AppendFormat("{0}\"{1}\":\"{2}\"", flag ? "," : null
|
||
, ConvertHelper.ConvertToClientString(s.Key).Trim()
|
||
, ConvertHelper.ConvertToClientString(s.Value).Trim());
|
||
|
||
flag = true;
|
||
}
|
||
sb.Append("}");
|
||
AddedKey = null;
|
||
}
|
||
if (sb.Length > 0)
|
||
{
|
||
sb.Insert(0, "{\n");
|
||
sb.Append("\n}");
|
||
}
|
||
if (ClientEvents != null && ClientEvents.Count > 0)
|
||
{
|
||
flag = false;
|
||
AddedKey = new Dictionary<string, object>();
|
||
foreach (var s in ClientEvents)
|
||
{
|
||
string k = s.EventName.ToString(), v = s.Handle;
|
||
if (string.IsNullOrWhiteSpace(v)) continue;
|
||
AddedKey.Add(k, null);
|
||
if (v.StartsWith("javascript:", StringComparison.CurrentCultureIgnoreCase))
|
||
{ v = "function(file,args){\n" + v.Substring(11) + "\n}"; }
|
||
sb.AppendFormat("{0}\"{1}\":{2}", flag ? "," : ",\n{\n", k, v);
|
||
flag = true;
|
||
}
|
||
if (flag)
|
||
{
|
||
sb.Append("\n}");
|
||
}
|
||
|
||
}
|
||
string js = "var " + this.ClientID + "=new Uploader(" + sb.ToString() + ")";
|
||
|
||
|
||
writer.Write("<script>\n"+js+"\n</script>");
|
||
}
|
||
protected override void CreateChildControls()
|
||
{
|
||
base.CreateChildControls();
|
||
if (ViewTemplate != null)
|
||
{
|
||
ViewTemplate item = new ViewTemplate();
|
||
ViewTemplate.InstantiateIn(item);
|
||
this.Controls.Add(item);
|
||
}
|
||
}
|
||
string GetWebResourceUrl(string rn)
|
||
{
|
||
return Page.ClientScript.GetWebResourceUrl(this.GetType(), rn);
|
||
}
|
||
void RegisterClientScript()
|
||
{
|
||
if (this.Page.Header != null)
|
||
{
|
||
string id = "Uploader.release.min.js";
|
||
if (this.Page.Header.FindControl(id) == null)
|
||
{
|
||
Control container = new Control();
|
||
container.ID = id;
|
||
HtmlGenericControl js = new HtmlGenericControl("script");
|
||
js.Attributes.Add("src", GetWebResourceUrl("Html5Uploader.Controls.Uploader.release.min.js"));
|
||
js.InnerHtml = " ";
|
||
container.Controls.Add(js);
|
||
Page.Header.Controls.Add(js);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|