添加项目文件。
This commit is contained in:
37
HTML5UploaderWebSiteTest.sln
Normal file
37
HTML5UploaderWebSiteTest.sln
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.779
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HTML5UploaderWebSiteTest", "Uploader\HTML5UploaderWebSiteTest.csproj", "{152482F9-A932-4C5A-914F-F7D646921286}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Html5Uploader", "Html5Uploader\Html5Uploader.csproj", "{07F2A054-679A-4AA7-8C78-DAFEBF6D2EEF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helper", "Helper\Helper.csproj", "{6C6C0829-DFB5-4AE1-B763-7803D23E17E9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{152482F9-A932-4C5A-914F-F7D646921286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{152482F9-A932-4C5A-914F-F7D646921286}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{152482F9-A932-4C5A-914F-F7D646921286}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{152482F9-A932-4C5A-914F-F7D646921286}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{07F2A054-679A-4AA7-8C78-DAFEBF6D2EEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07F2A054-679A-4AA7-8C78-DAFEBF6D2EEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07F2A054-679A-4AA7-8C78-DAFEBF6D2EEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07F2A054-679A-4AA7-8C78-DAFEBF6D2EEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C6C0829-DFB5-4AE1-B763-7803D23E17E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C6C0829-DFB5-4AE1-B763-7803D23E17E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C6C0829-DFB5-4AE1-B763-7803D23E17E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C6C0829-DFB5-4AE1-B763-7803D23E17E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DA7133B8-5E86-492C-8818-3DD6EC8C94D0}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
134
Helper/Convert.cs
Normal file
134
Helper/Convert.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Helper
|
||||
{
|
||||
public class ConvertHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 将数组转换为字符串
|
||||
/// </summary>
|
||||
/// <param name="arr"></param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertToStringFromIntArray(IEnumerable<int> arr)
|
||||
{
|
||||
return ConvertToStringFromIntArray(arr, true, "");
|
||||
}
|
||||
/// <summary>
|
||||
/// 将数组转换为字符串
|
||||
/// </summary>
|
||||
/// <param name="arr"></param>
|
||||
/// <param name="IgnoreZero">是否匆略数组中的零值</param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertToStringFromIntArray(IEnumerable<int> arr, bool IgnoreZero)
|
||||
{
|
||||
return ConvertToStringFromIntArray(arr, IgnoreZero, "");
|
||||
}
|
||||
/// <summary>
|
||||
/// 将数组转换为字符串
|
||||
/// </summary>
|
||||
/// <param name="arr"></param>
|
||||
/// <param name="IgnoreZero">是否匆略数组中的零值</param>
|
||||
/// <param name="SpaceTag">指定个间隔字符串</param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertToStringFromIntArray(IEnumerable<int> arr, bool IgnoreZero, string SpaceTag)
|
||||
{
|
||||
if (arr == null) return "";
|
||||
if (string.IsNullOrEmpty(SpaceTag))
|
||||
{
|
||||
SpaceTag = ",";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (int i in arr)
|
||||
{
|
||||
if (i == 0 && IgnoreZero) continue;
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
sb.Append(SpaceTag + i.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(i.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 字符串转换为整型数组
|
||||
/// </summary>
|
||||
/// <param name="src"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> ConvertToIntArrayFromString(string src)
|
||||
{
|
||||
return ConvertToIntArrayFromString(src, true, "");
|
||||
}
|
||||
/// <summary>
|
||||
/// 字符串转换为整型数组
|
||||
/// </summary>
|
||||
/// <param name="src"></param>
|
||||
/// <param name="IgnoreZero">是否匆略字符串中的零值</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> ConvertToIntArrayFromString(string src, bool IgnoreZero)
|
||||
{
|
||||
return ConvertToIntArrayFromString(src, IgnoreZero, "");
|
||||
}
|
||||
/// <summary>
|
||||
/// 字符串转换为整型数组
|
||||
/// </summary>
|
||||
/// <param name="src"></param>
|
||||
/// <param name="IgnoreZero">是否匆略字符串中的零值</param>
|
||||
/// <param name="SpaceTag">指定字符串中的间隔字符串</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> ConvertToIntArrayFromString(string src, bool IgnoreZero, string SpaceTag)
|
||||
{
|
||||
if (string.IsNullOrEmpty(src)) return null;
|
||||
if (string.IsNullOrEmpty(SpaceTag))
|
||||
{
|
||||
SpaceTag = ",";
|
||||
}
|
||||
string[] arr = src.Split(new string[] { SpaceTag }, StringSplitOptions.RemoveEmptyEntries);
|
||||
List<int> list = new List<int>();
|
||||
foreach (string i in arr)
|
||||
{
|
||||
int temp = 0;
|
||||
if (Int32.TryParse(i, out temp))
|
||||
{
|
||||
if (temp == 0 && IgnoreZero) continue;
|
||||
list.Add(temp);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回一个以逗号隔的ID列表
|
||||
/// 如果参数ListId为空或所有元数为0则抛出ArgumentException异常
|
||||
/// </summary>
|
||||
/// <param name="ListId"></param>
|
||||
/// <returns></returns>
|
||||
public static string ValidateListId(IEnumerable<int> ListId)
|
||||
{
|
||||
string IdStr = ConvertToStringFromIntArray(ListId);
|
||||
if (string.IsNullOrEmpty(IdStr) || IdStr.Trim()=="")
|
||||
{
|
||||
throw new ArgumentException("至少要指定一个ID");
|
||||
}
|
||||
return IdStr;
|
||||
}
|
||||
/// <summary>
|
||||
/// 转换到客户端字符串,将”"\n,\r“转换为客户端的转义字符
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertToClientString(string s)
|
||||
{
|
||||
return (s ?? "").Trim().Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "\\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
138
Helper/Helper.csproj
Normal file
138
Helper/Helper.csproj
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6C6C0829-DFB5-4AE1-B763-7803D23E17E9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>System.Helper</RootNamespace>
|
||||
<AssemblyName>Helper</AssemblyName>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<IsWebBootstrapper>true</IsWebBootstrapper>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>Jackson.pfx</AssemblyOriginatorKeyFile>
|
||||
<PublishUrl>http://localhost/Helper/</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Web</InstallFrom>
|
||||
<UpdateEnabled>true</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="HtmlAgilityPack">
|
||||
<HintPath>L:\学习\编程类\C#\DLL\html解析器\HtmlAgilityPack.1.4.6\Net40\HtmlAgilityPack.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.Entity">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.Entity.Design">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="XmlLinqExtensionMethods.cs" />
|
||||
<Compile Include="Convert.cs" />
|
||||
<Compile Include="Text.cs" />
|
||||
<Compile Include="PatulousMethods.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Url.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Jackson.pfx" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
15
Helper/PatulousMethods.cs
Normal file
15
Helper/PatulousMethods.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace System.Helper
|
||||
{
|
||||
public static class PatulousMethods
|
||||
{
|
||||
public static bool IsNumber(this string s)
|
||||
{
|
||||
return Regex.IsMatch(s, @"\d+");
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Helper/Properties/AssemblyInfo.cs
Normal file
41
Helper/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
[assembly: AllowPartiallyTrustedCallers()]
|
||||
// 有关程序集的常规信息通过下列属性集
|
||||
// 控制。更改这些属性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("Helper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("dog star")]
|
||||
[assembly: AssemblyProduct("Helper")]
|
||||
[assembly: AssemblyCopyright("版权所有 (C) dog star 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 使此程序集中的类型
|
||||
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
|
||||
// 则将该类型上的 ComVisible 属性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("9550217a-5d51-4bea-adbf-30b3fec86865")]
|
||||
|
||||
// 程序集的版本信息由下面四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 内部版本号
|
||||
// 修订号
|
||||
//
|
||||
// 可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值,
|
||||
// 方法是按如下所示使用“*”:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile(@"..\..\Jackson.pfx")]
|
||||
//[assembly: AssemblyKeyName("")]
|
||||
//[assembly: System.Security.AllowPartiallyTrustedCallers]
|
||||
196
Helper/Text.cs
Normal file
196
Helper/Text.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Web;
|
||||
|
||||
namespace System.Helper
|
||||
{
|
||||
public class Text
|
||||
{
|
||||
/// <summary>
|
||||
/// 截取指定长度的HTML
|
||||
/// </summary>
|
||||
/// <param name="html">被截取的HTML代码</param>
|
||||
/// <param name="textMaxLength">指定的长度</param>
|
||||
/// <param name="tags">要过滤的标签名称,例如:div </param>
|
||||
/// <returns>返回被截取后的html代码</returns>
|
||||
public static string InterceptHtml(string html, int textMaxLength, params string[] tags)
|
||||
{
|
||||
int o;
|
||||
return InterceptHtml(html, textMaxLength, out o, tags);
|
||||
}
|
||||
/// <summary>
|
||||
/// 截取指定长度的HTML
|
||||
/// </summary>
|
||||
/// <param name="html">被截取的HTML代码</param>
|
||||
/// <param name="textMaxLength">指定的长度</param>
|
||||
/// <param name="residualCount">输出剩余的数量</param>
|
||||
/// <param name="tags">要过滤的标签名称,例如:div </param>
|
||||
/// <returns>返回被截取后的html代码</returns>
|
||||
public static string InterceptHtml(string html, int textMaxLength, out int residualCount
|
||||
,params string[] tags )
|
||||
{
|
||||
residualCount = 0;
|
||||
if (string.IsNullOrEmpty(html) || html.Trim() == "")
|
||||
{ return html; }
|
||||
string str = "";
|
||||
html = FilterTag(html, tags);
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml("<root></root>");
|
||||
XmlNode n = doc.DocumentElement;
|
||||
n.InnerXml = html;
|
||||
int len = 0;
|
||||
residualCount = n.InnerText.Length - textMaxLength;
|
||||
if (residualCount < 0) residualCount = 0;
|
||||
if (n.HasChildNodes)
|
||||
{
|
||||
XmlNodeList ns = GetNodes(n);
|
||||
foreach (XmlNode t in ns)
|
||||
{
|
||||
if (t.InnerText.Trim() == "")
|
||||
{
|
||||
str += t.OuterXml;
|
||||
continue;
|
||||
}
|
||||
if (t.InnerText.Trim().Length <= textMaxLength - len)
|
||||
{
|
||||
str += t.OuterXml;
|
||||
len += t.InnerText.Trim().Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (t.NodeType == XmlNodeType.Text || (t.HasChildNodes && t.ChildNodes.Count == 1 && t.ChildNodes[0].NodeType == XmlNodeType.Text))
|
||||
{
|
||||
string text = t.InnerText.Trim();
|
||||
len = textMaxLength - len;
|
||||
text = text.Length > len ? text.Substring(0, len) : text;
|
||||
t.InnerText = text;
|
||||
str += t.OuterXml;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.InnerXml = InterceptHtml(t.InnerXml, textMaxLength - len);
|
||||
str += t.OuterXml;
|
||||
}
|
||||
break; ;
|
||||
}
|
||||
if (len >= textMaxLength)
|
||||
{ break; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string text = n.InnerText.Trim();
|
||||
text = text.Length > textMaxLength ? text.Substring(0, textMaxLength) : text;
|
||||
n.InnerText = text;
|
||||
str = n.OuterXml;
|
||||
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
}
|
||||
public static string Replace(string html, Regex rgx, MatchEvaluator evaluator)
|
||||
{
|
||||
if (string.IsNullOrEmpty(html) || html.Trim() == "")
|
||||
{ return html; }
|
||||
html = FilterTag(html, null);
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml("<root></root>");
|
||||
XmlNode n = doc.DocumentElement;
|
||||
n.InnerXml = html;
|
||||
Replace(n, rgx, evaluator);
|
||||
return n.InnerXml;
|
||||
}
|
||||
private static void Replace(XmlNode n, Regex rgx, MatchEvaluator evaluator)
|
||||
{
|
||||
|
||||
if (n.HasChildNodes)
|
||||
{
|
||||
XmlNodeList ns = GetNodes(n);
|
||||
foreach (XmlNode t in ns)
|
||||
{
|
||||
if (t.NodeType == XmlNodeType.Text)
|
||||
{
|
||||
if (t.InnerText.Trim() == "")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
t.InnerText = rgx.Replace(t.InnerText, evaluator);
|
||||
}
|
||||
else if(t.HasChildNodes){
|
||||
Replace(t, rgx, evaluator);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n.NodeType == XmlNodeType.Text)
|
||||
{
|
||||
if (n.InnerText.Trim() != "")
|
||||
{
|
||||
n.InnerText = rgx.Replace(n.InnerText, evaluator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static XmlNodeList GetNodes(XmlNode e)
|
||||
{
|
||||
return e.ChildNodes;
|
||||
}
|
||||
private static string FilterTag(string htm, string[] tags)
|
||||
{
|
||||
|
||||
Regex r;
|
||||
r = new Regex(@"</?\w+:\w+[^>]*>", RegexOptions.IgnoreCase);
|
||||
htm = r.Replace(htm, "");
|
||||
r = new Regex(@"<(\W)");
|
||||
htm = r.Replace(htm, m => m.Success && m.Groups[1].Value!="/" ? HttpUtility.HtmlEncode(m.Value) : m.Value);
|
||||
if (tags == null || tags.Length == 0)
|
||||
return htm;
|
||||
foreach (string t in tags)
|
||||
{
|
||||
r = new Regex(@"</?" + t + "[^>]*>", RegexOptions.IgnoreCase);
|
||||
htm = r.Replace(htm, "");
|
||||
}
|
||||
|
||||
return htm;
|
||||
}
|
||||
/// <summary>
|
||||
/// 截取指定长度的文本
|
||||
/// </summary>
|
||||
/// <param name="text">原文本</param>
|
||||
/// <param name="textMaxLength">最大长度</param>
|
||||
/// <returns></returns>
|
||||
public static string InterceptText(string text, int textMaxLength)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text) || text.Length <= textMaxLength) return text ?? "";
|
||||
return text.Substring(0, textMaxLength) + "...";
|
||||
}
|
||||
public static string Default(object text, params string[] DefaultValues)
|
||||
{
|
||||
return Default(text as string, DefaultValues);
|
||||
}
|
||||
public static string Default(string text,params string[] DefaultValues)
|
||||
{
|
||||
if (DefaultValues == null || DefaultValues.Length <= 0) return text;
|
||||
var v = text;int i = 0;
|
||||
while (string.IsNullOrWhiteSpace(v) && i < DefaultValues.Length)
|
||||
{
|
||||
v = DefaultValues[i];
|
||||
i++;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
public static string Trim(string text)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(text) ? string.Empty : text.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
28
Helper/Url.cs
Normal file
28
Helper/Url.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.UI;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
namespace System.Helper
|
||||
{
|
||||
public class Url
|
||||
{
|
||||
public static string GetRelativePath(string path)
|
||||
{
|
||||
Image img = new Image();
|
||||
img.ImageUrl = path;
|
||||
StringWriter sw = new StringWriter();
|
||||
HtmlTextWriter writer = new HtmlTextWriter(sw);
|
||||
img.RenderControl(writer);
|
||||
Regex rgx = new Regex(@"src=""([^\""]+)""", RegexOptions.IgnoreCase);
|
||||
Match m = rgx.Match(sw.ToString());
|
||||
if (!m.Success)
|
||||
{ return path; }
|
||||
return m.Groups[1].Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
387
Helper/XmlLinqExtensionMethods.cs
Normal file
387
Helper/XmlLinqExtensionMethods.cs
Normal file
@@ -0,0 +1,387 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using HtmlAgilityPack;
|
||||
|
||||
namespace System.Xml.Linq
|
||||
{
|
||||
public static class XmlLinqExtensionMethods
|
||||
|
||||
{
|
||||
public static XElement Attr(this XElement e, string name, object value)
|
||||
{
|
||||
if (e == null||string.IsNullOrEmpty(name)) return e;
|
||||
XAttribute attr = e.Attribute(name);
|
||||
if (attr == null)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
e.Add(new XAttribute(name, value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (value == null) {
|
||||
attr.Remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
attr.Value = Convert.ToString(value);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
public static string Attr(this XElement e, string name)
|
||||
{
|
||||
XAttribute attr = e == null || string.IsNullOrEmpty(name) ? null : e.Attribute(name);
|
||||
return attr == null ? string.Empty : HttpUtility.HtmlDecode(attr.Value);
|
||||
}
|
||||
public static T Attr<T>(this XElement e, string name) where T : struct
|
||||
{
|
||||
return e.AttrStruct<T>(name, default(T));
|
||||
}
|
||||
public static T AttrStruct<T>(this XElement e, string name, T defaultValue = default(T)) where T : struct
|
||||
{
|
||||
string v = e.Attr(name);
|
||||
if (string.IsNullOrWhiteSpace(v)) return defaultValue;
|
||||
Type t = typeof(T);
|
||||
try
|
||||
{
|
||||
if (t.IsEnum)
|
||||
{
|
||||
return (T)Enum.Parse(t, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (T)Convert.ChangeType(v, t);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
if (t == typeof(Guid))
|
||||
{
|
||||
object o = new Guid(v);
|
||||
return (T)o;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static string Attr(this HtmlNode e, string name)
|
||||
{
|
||||
var attr = e == null || !e.HasAttributes || string.IsNullOrEmpty(name) ? null : e.Attributes[name];
|
||||
return attr == null ? string.Empty : HttpUtility.HtmlDecode(attr.Value);
|
||||
}
|
||||
public static T Attr<T>(this HtmlNode e, string name) where T : struct
|
||||
{
|
||||
return e.AttrStruct<T>(name, default(T));
|
||||
}
|
||||
public static T AttrStruct<T>(this HtmlNode e, string name, T defaultValue = default(T)) where T : struct
|
||||
{
|
||||
string v = e.Attr(name);
|
||||
if (string.IsNullOrWhiteSpace(v)) return defaultValue;
|
||||
Type t = typeof(T);
|
||||
try
|
||||
{
|
||||
if (t.IsEnum)
|
||||
{
|
||||
return (T)Enum.Parse(t, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (T)Convert.ChangeType(v, t);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (t == typeof(Guid))
|
||||
{
|
||||
object o = new Guid(v);
|
||||
return (T)o;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
public static string Text(this HtmlNode e)
|
||||
{
|
||||
return e != null ? e.InnerText : string.Empty;
|
||||
}
|
||||
public static string Html(this HtmlNode e)
|
||||
{
|
||||
return e != null ? e.InnerHtml : string.Empty;
|
||||
}
|
||||
|
||||
public static bool HasClass(this HtmlNode node,string className)
|
||||
{
|
||||
string es = Regex.Escape(className);
|
||||
var rgx = new Regex(@"(\s+" + es + @"\s*$)|(^\s*" + es + @"\s+)|(\s+" + es + @"\s+)");
|
||||
var v = node.Attr("class").Trim();
|
||||
return v != "" && (v == className || rgx.IsMatch(v));
|
||||
}
|
||||
public static HtmlNode GetNodeByClasName(this HtmlNode node, string className)
|
||||
{
|
||||
if (!node.HasChildNodes) return null;
|
||||
var nodes = node.ChildNodes;
|
||||
foreach (var item in nodes)
|
||||
{
|
||||
if (item.NodeType != HtmlNodeType.Element) continue;
|
||||
if (item.HasClass(className))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
var o = item.GetNodeByClasName(className);
|
||||
if (o != null) return o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HtmlNode GetNodeByTagName(this HtmlNode node, string tagName)
|
||||
{
|
||||
if (!node.HasChildNodes||string.IsNullOrWhiteSpace(tagName)) return null;
|
||||
var nodes = node.ChildNodes;
|
||||
foreach (var item in nodes)
|
||||
{
|
||||
if (item.NodeType != HtmlNodeType.Element) continue;
|
||||
if (string.Equals(tagName,item.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
var o = item.GetNodeByTagName(tagName);
|
||||
if (o != null) return o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static HtmlNode GetNodeById(this HtmlNode node, string id)
|
||||
{
|
||||
if (!node.HasChildNodes || string.IsNullOrWhiteSpace(id)) return null;
|
||||
var nodes = node.ChildNodes;
|
||||
foreach (var item in nodes)
|
||||
{
|
||||
if (item.NodeType != HtmlNodeType.Element) continue;
|
||||
if (string.Equals(id, item.Attr("id"), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
var o = item.GetNodeById(id);
|
||||
if (o != null) return o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<HtmlNode> GetNodesByClasName(this HtmlNode node, string className)
|
||||
{
|
||||
if (!node.HasChildNodes) return null;
|
||||
var nodes = node.ChildNodes;
|
||||
var list = new List<HtmlNode>();
|
||||
|
||||
foreach (var item in nodes)
|
||||
{
|
||||
if (item.NodeType != HtmlNodeType.Element) continue;
|
||||
if (item.HasClass(className))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
list.AddRange(item.GetNodesByClasName(className));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static IEnumerable<HtmlNode> GetNodesByTagName(this HtmlNode node, string tagName)
|
||||
{
|
||||
if (!node.HasChildNodes || string.IsNullOrWhiteSpace(tagName)) return null;
|
||||
var nodes = node.ChildNodes;
|
||||
var list = new List<HtmlNode>();
|
||||
foreach (var item in nodes)
|
||||
{
|
||||
if (item.NodeType != HtmlNodeType.Element) continue;
|
||||
|
||||
if (string.Equals(tagName, item.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
list.AddRange(item.GetNodesByTagName(tagName));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public static IEnumerable<HtmlNode> AncestorNodes(this HtmlNode node)
|
||||
{
|
||||
var n = node;
|
||||
do {
|
||||
if (n != null)
|
||||
{
|
||||
n = n.ParentNode;
|
||||
if (n != null && n.NodeType== HtmlNodeType.Element) yield return n;
|
||||
}
|
||||
} while (n != null);
|
||||
|
||||
|
||||
}
|
||||
public static bool Is(this HtmlNode node, string[] selectors)
|
||||
{
|
||||
if (node == null || node.NodeType != HtmlNodeType.Element || selectors == null || selectors.Length == 0) return false;
|
||||
return selectors.Where(s => node.Is(s)).Any();
|
||||
}
|
||||
static bool IsMatch(HtmlNode e, string s)
|
||||
{
|
||||
|
||||
var tagRgx = new Regex(@"^\w+", RegexOptions.IgnoreCase);
|
||||
var classRgx = new Regex(@"\.[a-zA-Z_\-]+");
|
||||
var idRgx = new Regex(@"#[a-zA-Z_\-]+");
|
||||
|
||||
var css = e.Attr("class");
|
||||
var tagMatch = tagRgx.Match(s);
|
||||
var idMatch = idRgx.Match(s);
|
||||
var classMatches = classRgx.Matches(s);
|
||||
var matched = (tagMatch == null || !tagMatch.Success || string.Equals(tagMatch.Value, e.Name, StringComparison.OrdinalIgnoreCase))
|
||||
&& (idMatch == null || !idMatch.Success || string.Equals(idMatch.Value.TrimStart('#'), e.Attr("id"), StringComparison.Ordinal))
|
||||
&& (classMatches == null || classMatches.Count == 0 || (
|
||||
from n in classMatches.OfType<Match>()
|
||||
join c in css.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(o => "." + o)
|
||||
on n.Value equals c
|
||||
select c
|
||||
).Count() == classMatches.Count);
|
||||
return matched;
|
||||
}
|
||||
public static bool Is(this HtmlNode node, string selector)
|
||||
{
|
||||
if(node==null || node.NodeType!= HtmlNodeType.Element || string.IsNullOrWhiteSpace(selector)) return false;
|
||||
//string[] arr = selector.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries).Reverse().ToArray();
|
||||
selector = Regex.Replace(selector, @"\s*\>\s*", ">");
|
||||
Func<string, Tuple<string[], bool>> lastSplit = s => {
|
||||
int i1 = s.LastIndexOf('>'), i2 = s.LastIndexOf(' ');
|
||||
if (i1 < 0 && i2 < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = Math.Max(i1, i2);
|
||||
return new Tuple<string[], bool>(new string[] { s.Substring(i + 1).Trim(), s.Substring(0, i).Trim() }, i1 > 0 && i1 > i2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var current = node;
|
||||
string sltrs = selector;
|
||||
do
|
||||
{
|
||||
var tu = lastSplit(sltrs);
|
||||
string sltr;
|
||||
if (tu == null)
|
||||
{
|
||||
sltr = sltrs;
|
||||
sltrs = null;
|
||||
}
|
||||
else {
|
||||
sltr = tu.Item1[0];
|
||||
sltrs = tu.Item1[1];
|
||||
}
|
||||
var m = IsMatch(current,sltr);
|
||||
if (!m) return false;
|
||||
if (tu != null && !tu.Item2)
|
||||
{
|
||||
bool nearMatched = false;
|
||||
tu = lastSplit(sltrs);
|
||||
sltr = tu == null ? sltrs : tu.Item1[0];
|
||||
foreach (var e in current.AncestorNodes())
|
||||
{
|
||||
nearMatched = IsMatch(e, sltr);
|
||||
if (nearMatched)
|
||||
{
|
||||
current = e.ParentNode;
|
||||
sltrs = tu == null ? null : tu.Item1[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nearMatched) return false;
|
||||
}
|
||||
else {
|
||||
current = current.ParentNode;
|
||||
}
|
||||
|
||||
} while (sltrs != null);
|
||||
return true;
|
||||
}
|
||||
public static IEnumerable<HtmlNode> GetNodes(this HtmlNode node, string selectors)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(selectors) ? node.Descendants() : from n in node.Descendants()
|
||||
where n.Is(selectors.Split(','))
|
||||
select n;
|
||||
|
||||
}
|
||||
public static IEnumerable<HtmlNode> Before(this HtmlNode node, Func<HtmlNode, bool> assert=null)
|
||||
{
|
||||
var n =node==null?null: node.PreviousSibling;
|
||||
do {
|
||||
if (n != null)
|
||||
{
|
||||
if (assert == null || assert(n)) yield return n;
|
||||
n = n.PreviousSibling;
|
||||
}
|
||||
}
|
||||
while (n != null);
|
||||
|
||||
}
|
||||
public static IEnumerable<HtmlNode> Behind(this HtmlNode node, Func<HtmlNode, bool> assert = null)
|
||||
{
|
||||
var n = node == null ? null : node.NextSibling;
|
||||
do
|
||||
{
|
||||
if (n != null)
|
||||
{
|
||||
if (assert == null || assert(n)) yield return n;
|
||||
n = n.NextSibling;
|
||||
}
|
||||
}
|
||||
while (n != null);
|
||||
|
||||
}
|
||||
public static HtmlNode Prev(this HtmlNode node)
|
||||
{
|
||||
do
|
||||
{
|
||||
node = node != null ? node.PreviousSibling : null;
|
||||
} while (node != null && node.NodeType != HtmlNodeType.Element);
|
||||
return node;
|
||||
}
|
||||
public static HtmlNode Next(this HtmlNode node)
|
||||
{
|
||||
do
|
||||
{
|
||||
node = node != null ? node.NextSibling : null;
|
||||
} while (node != null && node.NodeType != HtmlNodeType.Element);
|
||||
return node;
|
||||
}
|
||||
public static HtmlNode First(this IEnumerable<HtmlNode> nodes, string tagName = null)
|
||||
{
|
||||
if (nodes == null) return null;
|
||||
return string.IsNullOrWhiteSpace(tagName) ? nodes.FirstOrDefault()
|
||||
: (from n in nodes
|
||||
where n.NodeType == HtmlNodeType.Element && string.Equals(n.Name, tagName, StringComparison.OrdinalIgnoreCase)
|
||||
select n).FirstOrDefault();
|
||||
}
|
||||
|
||||
|
||||
public static HtmlNode First(this HtmlNodeCollection nodes, string tagName = null)
|
||||
{
|
||||
if (nodes == null || nodes.Count == 0) return null;
|
||||
return nodes.Cast<HtmlNode>().First(tagName);
|
||||
}
|
||||
public static HtmlNode Last(this IEnumerable<HtmlNode> nodes, string tagName = null)
|
||||
{
|
||||
if (nodes == null) return null;
|
||||
return string.IsNullOrWhiteSpace(tagName) ? nodes.LastOrDefault()
|
||||
: (from n in nodes
|
||||
where n.NodeType == HtmlNodeType.Element && string.Equals(n.Name, tagName, StringComparison.OrdinalIgnoreCase)
|
||||
select n).LastOrDefault();
|
||||
}
|
||||
public static HtmlNode Last(this HtmlNodeCollection nodes,string tagName=null)
|
||||
{
|
||||
if (nodes == null || nodes.Count == 0) return null;
|
||||
return nodes.Cast<HtmlNode>().Last(tagName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
40
Html5Uploader/Controls/ClientEventsCollection.cs
Normal file
40
Html5Uploader/Controls/ClientEventsCollection.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Html5Uploader.Controls
|
||||
{
|
||||
public class ClientEventsCollection : List<ClientEvent>
|
||||
{
|
||||
public ClientEvent this[ClientEventsNames name]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Find(p => p.EventName == name);
|
||||
}
|
||||
set
|
||||
{
|
||||
ClientEvent par = this[name];
|
||||
if (par == null)
|
||||
{
|
||||
par.EventName = value.EventName;
|
||||
par.Handle = value.Handle;
|
||||
}
|
||||
else { Add(value); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ClientEvent
|
||||
{
|
||||
public ClientEvent() { }
|
||||
public ClientEvent(ClientEventsNames n, string v)
|
||||
{ EventName = n; Handle = v; }
|
||||
public ClientEventsNames EventName { get; set; }
|
||||
public string Handle { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
81
Html5Uploader/Controls/Enums.cs
Normal file
81
Html5Uploader/Controls/Enums.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Html5Uploader.Controls
|
||||
{
|
||||
public enum SettingsNames
|
||||
{
|
||||
placeholder
|
||||
,
|
||||
multiple
|
||||
,
|
||||
accept
|
||||
,
|
||||
types
|
||||
,
|
||||
timeout
|
||||
,
|
||||
maxQueue
|
||||
,
|
||||
dragable
|
||||
,
|
||||
dragContainer
|
||||
,
|
||||
progress
|
||||
,
|
||||
blobSize
|
||||
,
|
||||
sliced
|
||||
,
|
||||
limitSize
|
||||
,
|
||||
url
|
||||
,
|
||||
parseResult
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum ClientEventsNames
|
||||
{
|
||||
selecting
|
||||
,
|
||||
validate
|
||||
,
|
||||
selected
|
||||
,
|
||||
upload
|
||||
,
|
||||
createProgress
|
||||
,
|
||||
getResumableInfoHandler
|
||||
,
|
||||
progress
|
||||
,
|
||||
complete
|
||||
,
|
||||
success
|
||||
,
|
||||
error
|
||||
,
|
||||
cancel
|
||||
,
|
||||
proceed
|
||||
,
|
||||
pause
|
||||
,
|
||||
drop
|
||||
,
|
||||
dragover
|
||||
,
|
||||
dragleave
|
||||
|
||||
}
|
||||
|
||||
public enum UploaderSliceds
|
||||
{
|
||||
Auto = 0, Enabled = 1, Disabled = 2
|
||||
}
|
||||
}
|
||||
410
Html5Uploader/Controls/Html5UploaderClient.cs
Normal file
410
Html5Uploader/Controls/Html5UploaderClient.cs
Normal file
@@ -0,0 +1,410 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Html5Uploader/Controls/PostParametersCollection.cs
Normal file
36
Html5Uploader/Controls/PostParametersCollection.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Html5Uploader.Controls
|
||||
{
|
||||
public class PostParametersCollection : List<PostParameter>
|
||||
{
|
||||
public PostParametersCollection()
|
||||
: base()
|
||||
{ }
|
||||
public PostParameter this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Find(p => string.Equals(key, p.Key, StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
set
|
||||
{
|
||||
PostParameter par = this.Find(p => string.Equals(key, p.Key
|
||||
, StringComparison.CurrentCultureIgnoreCase));
|
||||
par.Key = value.Key;
|
||||
par.Value = value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class PostParameter
|
||||
{
|
||||
public PostParameter() { }
|
||||
public PostParameter(string k, string v)
|
||||
{ Key = k; Value = v; }
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
1
Html5Uploader/Controls/Uploader.release.min.js
vendored
Normal file
1
Html5Uploader/Controls/Uploader.release.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
12
Html5Uploader/Controls/ViewTemplate.cs
Normal file
12
Html5Uploader/Controls/ViewTemplate.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.UI;
|
||||
|
||||
namespace Html5Uploader.Controls
|
||||
{
|
||||
public class ViewTemplate : Control, INamingContainer
|
||||
{
|
||||
}
|
||||
}
|
||||
47
Html5Uploader/FileUploadComplete.cs
Normal file
47
Html5Uploader/FileUploadComplete.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Html5Uploader
|
||||
{
|
||||
public class FileUploadComplete
|
||||
{
|
||||
|
||||
public FileUploadComplete(string FilePath, long Size, string Message, Exception error = null)
|
||||
{
|
||||
this.FilePath = FilePath;
|
||||
this.Message = Message;
|
||||
this.Error = error;
|
||||
this.Size = Size;
|
||||
}
|
||||
public FileUploadComplete(string FilePath,long Size, bool Sliced = false, long BlobIndex = 0, long BlobCount = 1, string Message = null, Exception error = null)
|
||||
: this(FilePath, Size, Message, error)
|
||||
{
|
||||
this.Sliced = Sliced;
|
||||
this.BlobCount = BlobCount;
|
||||
this.BlobIndex = BlobIndex;
|
||||
}
|
||||
public long Size { get; private set; }
|
||||
public bool Sliced { get; private set; }
|
||||
public long BlobIndex { get; private set; }
|
||||
public long BlobCount { get; private set; }
|
||||
public string FilePath { get; private set; }
|
||||
string _fileName;
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_fileName == null && !string.IsNullOrWhiteSpace(FilePath))
|
||||
{
|
||||
_fileName = Path.GetFileName(FilePath);
|
||||
}
|
||||
return _fileName;
|
||||
}
|
||||
}
|
||||
public Exception Error { get;private set; }
|
||||
public string Message { get;set; }
|
||||
public object Context { get; set; }
|
||||
}
|
||||
}
|
||||
529
Html5Uploader/FilesUploadHandler.cs
Normal file
529
Html5Uploader/FilesUploadHandler.cs
Normal file
@@ -0,0 +1,529 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Helper;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Security;
|
||||
using System.Web.SessionState;
|
||||
|
||||
namespace Html5Uploader
|
||||
{
|
||||
public class InvalidDataBlobException : Exception
|
||||
{
|
||||
public InvalidDataBlobException() { }
|
||||
public InvalidDataBlobException(string message):base(message) { }
|
||||
public InvalidDataBlobException(string message, Exception innerException) : base(message, innerException) { }
|
||||
public InvalidDataBlobException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
public class ValidateArguments {
|
||||
public ValidateArguments(HttpPostedFile file, string fileName, string[] accepts)
|
||||
{
|
||||
this.File = file;
|
||||
this.AcceptsTypes = accepts;
|
||||
this.Validation = true;
|
||||
this.FileName = fileName;
|
||||
}
|
||||
public HttpPostedFile File { get; private set; }
|
||||
public string FileName { get; private set; }
|
||||
public string[] AcceptsTypes { get; private set; }
|
||||
public bool Validation { get; set; }
|
||||
}
|
||||
public class CompleteArguments {
|
||||
public CompleteArguments(IEnumerable<FileUploadComplete> data)
|
||||
{
|
||||
FileUploadCompletes = data;
|
||||
}
|
||||
public bool Cancel { get; set; }
|
||||
public IEnumerable<FileUploadComplete> FileUploadCompletes { get;private set; }
|
||||
}
|
||||
public class FilesUploadHandler : IHttpHandler,IDisposable,IRequiresSessionState
|
||||
{
|
||||
public event Action<FilesUploadHandler, Exception> Error;
|
||||
public event Action<FilesUploadHandler, CompleteArguments> Complete;
|
||||
public event Action<FilesUploadHandler, ValidateArguments> Validate;
|
||||
#region 可续传处理块
|
||||
ResumableInfoProvider _provider;
|
||||
protected virtual ResumableInfoProvider Provider {
|
||||
get {
|
||||
if (_provider == null)
|
||||
{
|
||||
_provider = new ResumableInfoXmlProvider();
|
||||
}
|
||||
return _provider;
|
||||
}
|
||||
}
|
||||
bool? _sliced;
|
||||
protected bool Sliced {
|
||||
get {
|
||||
if (!_sliced.HasValue)
|
||||
{
|
||||
bool t;
|
||||
_sliced = bool.TryParse(Form["sliced"] ?? Request.QueryString["sliced"], out t) && t;
|
||||
}
|
||||
return _sliced.Value;
|
||||
}
|
||||
}
|
||||
long? _blobIndex;
|
||||
protected long BlobIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_blobIndex.HasValue)
|
||||
{
|
||||
long t;
|
||||
_blobIndex = long.TryParse(Form["blobIndex"] ?? Request.QueryString["blobIndex"], out t) ? t : 0;
|
||||
}
|
||||
return _blobIndex.Value;
|
||||
}
|
||||
}
|
||||
long? _blobCount;
|
||||
protected long BlobCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_blobCount.HasValue)
|
||||
{
|
||||
long t;
|
||||
_blobCount = long.TryParse(Form["blobCount"] ?? Request.QueryString["blobCount"], out t) ? t : 1;
|
||||
}
|
||||
return _blobCount.Value;
|
||||
}
|
||||
}
|
||||
long? _blobSize;
|
||||
protected long BlobSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_blobSize.HasValue)
|
||||
{
|
||||
long t;
|
||||
_blobSize = long.TryParse(Form["blobSize"] ?? Request.QueryString["blobSize"], out t) ? t : 0;
|
||||
}
|
||||
return _blobSize.Value;
|
||||
}
|
||||
}
|
||||
long? _fileSize;
|
||||
protected long FileSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_fileSize.HasValue)
|
||||
{
|
||||
long t;
|
||||
if (Sliced)
|
||||
{
|
||||
_fileSize = long.TryParse(Form["fileSize"] ?? Request.QueryString["fileSize"], out t) ? t : 0;
|
||||
}
|
||||
else {
|
||||
_fileSize = HasFiles ? Files[0].ContentLength : 0;
|
||||
}
|
||||
}
|
||||
return _fileSize.Value;
|
||||
}
|
||||
}
|
||||
Guid? _key;
|
||||
protected Guid ResumableKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_key.HasValue)
|
||||
{
|
||||
Guid t;
|
||||
_key = Guid.TryParse(Form["resumableKey"] ?? Request.QueryString["resumableKey"], out t) ? t : Guid.Empty;
|
||||
}
|
||||
return _key.Value;
|
||||
}
|
||||
}
|
||||
string _fileName;
|
||||
protected string FileName {
|
||||
get
|
||||
{
|
||||
if (_fileName == null) {
|
||||
_fileName = Sliced ? (Form["fileName"] ?? Request.QueryString["fileName"]) : HasFiles ? Files[0].FileName : string.Empty;
|
||||
}
|
||||
return _fileName;
|
||||
}
|
||||
}
|
||||
string _fileType;
|
||||
protected string FileType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_fileType == null)
|
||||
{
|
||||
_fileType = Sliced ? (Form["fileType"] ?? Request.QueryString["fileType"]) : (HasFiles ? Files[0].ContentType : string.Empty);
|
||||
|
||||
}
|
||||
return _fileType;
|
||||
}
|
||||
}
|
||||
ResumableInfo _resumableInfo;
|
||||
protected virtual ResumableInfo ResumableInfo
|
||||
{
|
||||
get {
|
||||
if (_resumableInfo == null)
|
||||
{
|
||||
_resumableInfo = ResumableKey == Guid.Empty ? Provider.GetResumableInfo(FileName, FileType, FileSize, BlobSize, BlobCount) : Provider.GetResumableInfo(ResumableKey);
|
||||
if (_resumableInfo == null && Guid.Empty != ResumableKey)
|
||||
{
|
||||
throw new ArgumentException("无效的键值");
|
||||
}
|
||||
///如果已经上传了部分文件,且部件文件已丢失,那么重新再传。
|
||||
if (_resumableInfo != null && !string.IsNullOrWhiteSpace(_resumableInfo.StorePath) && !File.Exists(Context.Server.MapPath("~" + _resumableInfo.StorePath)))
|
||||
{
|
||||
Provider.DeleteResumableInfo(_resumableInfo.Key);
|
||||
_resumableInfo = null;
|
||||
}
|
||||
|
||||
if (_resumableInfo == null)
|
||||
{
|
||||
_resumableInfo = new ResumableInfo(FileName, FileType,null, FileSize, BlobSize, BlobCount);
|
||||
}
|
||||
}
|
||||
return _resumableInfo;
|
||||
}
|
||||
}
|
||||
protected virtual void SaveResumableInfo(ResumableInfo info)
|
||||
{
|
||||
Provider.SaveResumableInfo(info);
|
||||
}
|
||||
protected virtual void RemoveResumableInfo(ResumableInfo info)
|
||||
{
|
||||
Provider.DeleteResumableInfo(info.Key);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 属性
|
||||
string[] _types;
|
||||
string[] AcceptsTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_types == null)
|
||||
{
|
||||
_types = string.IsNullOrWhiteSpace(Form["types"]) ? new string[0] : Form["types"].Trim().Split(';');
|
||||
}
|
||||
return _types;
|
||||
}
|
||||
}
|
||||
|
||||
string _token;
|
||||
protected string Token {
|
||||
|
||||
get {
|
||||
if (_token == null)
|
||||
{
|
||||
_token = Form["token"] ?? string.Empty;
|
||||
}
|
||||
return _token;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HttpContext _context;
|
||||
protected HttpContext Context { get { return _context; } }
|
||||
protected HttpRequest Request { get { return _context != null ? _context.Request : null; } }
|
||||
protected NameValueCollection Form { get { return Request == null ? null : Request.Form; } }
|
||||
protected HttpResponse Response { get { return _context != null ? _context.Response : null; } }
|
||||
protected IPrincipal User { get { return _context == null ? null : _context.User; } }
|
||||
protected HttpFileCollection Files { get { return Request != null ? Request.Files : null; } }
|
||||
protected bool HasFiles { get { return Files != null && Files.Count > 0; } }
|
||||
protected bool IsAuthenticated { get { return User != null && User.Identity != null && User.Identity.IsAuthenticated; } }
|
||||
#endregion
|
||||
|
||||
#region IHttpHandler 成员
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
public void ProcessRequest(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context = context;
|
||||
Init();
|
||||
////////验证用户的合法身份
|
||||
//if (!IsAuthenticated)
|
||||
//{ throw new HttpException(503, null); }
|
||||
string method = Request.QueryString["method"] ?? Form["method"];
|
||||
switch (method)
|
||||
{
|
||||
case "getResumableInfo":
|
||||
Response.Clear();
|
||||
Response.Write(string.Format("{{key:\"{0}\",index:{1}}}", ResumableInfo.Key, ResumableInfo.BlobIndex));
|
||||
SaveResumableInfo(ResumableInfo);
|
||||
return;
|
||||
case "deleteResumable":
|
||||
Response.Clear();
|
||||
DeleteResumable();
|
||||
Response.Write("true");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
var outputs=Save();
|
||||
if (Sliced)
|
||||
{
|
||||
if (BlobIndex >= BlobCount - 1)
|
||||
{
|
||||
RemoveResumableInfo(ResumableInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveResumableInfo(ResumableInfo);
|
||||
}
|
||||
}
|
||||
bool completed = false;
|
||||
if (Complete != null && (!Sliced||(Sliced && BlobIndex >= BlobCount - 1)))
|
||||
{
|
||||
CompleteArguments arg = new CompleteArguments(outputs);
|
||||
Complete(this, arg);
|
||||
completed = arg.Cancel;
|
||||
}
|
||||
if (!completed)
|
||||
{
|
||||
if (outputs == null)
|
||||
{
|
||||
Response.Write("null");
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var fuc in outputs)
|
||||
{
|
||||
sb.Append((sb.Length > 0 ? "," : "") + GetJSON(fuc));
|
||||
}
|
||||
if (outputs.Count() > 1)
|
||||
{
|
||||
sb.Insert(0, "[");
|
||||
sb.Append("]");
|
||||
}
|
||||
Response.Write(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exp) {
|
||||
if (exp is InvalidDataBlobException || exp.InnerException is InvalidDataBlobException)
|
||||
{ DeleteResumable(); }
|
||||
if (Error != null)
|
||||
{
|
||||
Error(this, exp);
|
||||
}
|
||||
else {
|
||||
Response.Clear();
|
||||
Response.Write("{\"err\":true,\"msg\":\"" + ConvertHelper.ConvertToClientString(exp.Message) + "\"}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
string _storeDirectory;
|
||||
protected virtual string StoreDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_storeDirectory == null)
|
||||
{
|
||||
string p = (WebConfigurationManager.AppSettings["Html5Uploader:FilesStoreDirectory"] ?? "").Trim().Replace('\\', '/');
|
||||
if (0 == p.Length)
|
||||
{
|
||||
p = "/files";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p.StartsWith("~/"))
|
||||
{
|
||||
p = p.TrimStart('~');
|
||||
}
|
||||
else if (!p.StartsWith("/"))
|
||||
{
|
||||
p = "/" + p;
|
||||
}
|
||||
}
|
||||
_storeDirectory = p;
|
||||
}
|
||||
return _storeDirectory;
|
||||
}
|
||||
}
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (_provider != null)
|
||||
{ _provider.Dispose(); }
|
||||
}
|
||||
protected virtual string CreateStorePath(string directory)
|
||||
{
|
||||
string AbsoluteUploadDirectory = Context.Server.MapPath("~" + directory)
|
||||
, n = Path.GetFileNameWithoutExtension(FileName)
|
||||
, ext = Path.GetExtension(FileName)
|
||||
, p = Path.Combine(AbsoluteUploadDirectory, n + ext);
|
||||
int i = 0;
|
||||
while (File.Exists(p))
|
||||
{
|
||||
p = Path.Combine(AbsoluteUploadDirectory, n + "(" + (++i) + ")" + ext);
|
||||
}
|
||||
return Path.Combine(directory, Path.GetFileName(p)).Replace("\\", "/");
|
||||
}
|
||||
protected virtual string CreateStorePath()
|
||||
{
|
||||
return CreateStorePath(StoreDirectory);
|
||||
}
|
||||
protected virtual void Init() {}
|
||||
protected virtual string GetJSON(FileUploadComplete fuc)
|
||||
{
|
||||
bool err = false;
|
||||
if (fuc.Error != null)
|
||||
{
|
||||
err = true;
|
||||
if (string.IsNullOrWhiteSpace(fuc.Message)) { fuc.Message = fuc.Error.Message; }
|
||||
}
|
||||
return string.Format("{{{0}\"msg\":\"{1}\",\"filePath\":\"{2}\",\"name\":\"{3}\"{4}}}"
|
||||
, err ? "\"err\":true," : null
|
||||
, err ? fuc.Message : string.IsNullOrWhiteSpace(fuc.Message) ? "文件保存成功" : ConvertHelper.ConvertToClientString(fuc.Message)
|
||||
, ConvertHelper.ConvertToClientString(fuc.FilePath), ConvertHelper.ConvertToClientString(fuc.FileName)
|
||||
, fuc.Sliced ? string.Format(",\"sliced\":true,\"blobIndex\":{0},\"blobCount\":{1}", fuc.BlobIndex, fuc.BlobCount) : null);
|
||||
}
|
||||
protected bool IsValidation(HttpPostedFile file)
|
||||
{
|
||||
if (Sliced)
|
||||
{
|
||||
if (file != null && file.InputStream.Length > ResumableInfo.BlobSize)
|
||||
{
|
||||
throw new InvalidDataBlobException("无效的数据包。");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(ResumableInfo.StorePath))
|
||||
{
|
||||
string physicalPath = Context.Server.MapPath("~" + ResumableInfo.StorePath);
|
||||
if (File.Exists(physicalPath) && new FileInfo(physicalPath).Length + file.InputStream.Length > ResumableInfo.FileSize)
|
||||
{
|
||||
throw new InvalidDataBlobException("无效的数据包。");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool validation = false;
|
||||
string name = Sliced ? FileName : file.FileName;
|
||||
if (AcceptsTypes == null || AcceptsTypes.Length == 0) { validation = true; }
|
||||
else
|
||||
{
|
||||
foreach (var accept in AcceptsTypes)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(accept)) continue;
|
||||
if (Regex.IsMatch(name, Regex.Escape(accept.Trim()) + "$", RegexOptions.IgnoreCase))
|
||||
{
|
||||
validation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Validate != null)
|
||||
{
|
||||
string fileName=Sliced?FileName:Path.GetFileName(file.FileName);
|
||||
ValidateArguments args = new ValidateArguments(file, fileName, AcceptsTypes);
|
||||
args.Validation = validation;
|
||||
Validate(this, args);
|
||||
validation = args.Validation;
|
||||
}
|
||||
return validation;
|
||||
}
|
||||
protected virtual IEnumerable<FileUploadComplete> Save() {
|
||||
FileUploadComplete fuc = null;
|
||||
if (HasFiles)
|
||||
{
|
||||
if (Sliced)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < Files.Count; i++)
|
||||
{
|
||||
HttpPostedFile f = Files[i];
|
||||
fuc = SaveFile(f);
|
||||
}
|
||||
}
|
||||
catch (Exception exp) { fuc = new FileUploadComplete(this.FileName,FileSize,true, ResumableInfo.BlobIndex, ResumableInfo.BlobCount, null, exp); }
|
||||
return new FileUploadComplete[] { fuc };
|
||||
}
|
||||
else
|
||||
{
|
||||
List<FileUploadComplete> list = new List<FileUploadComplete>();
|
||||
for (int i = 0; i < Files.Count; i++)
|
||||
{
|
||||
HttpPostedFile f = Files[i];
|
||||
try
|
||||
{
|
||||
fuc = SaveFile(f);
|
||||
}
|
||||
catch (Exception exp) {
|
||||
fuc = new FileUploadComplete(f.FileName,f.ContentLength,null, exp);
|
||||
}
|
||||
list.Add(fuc);
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected virtual FileUploadComplete SaveFile(HttpPostedFile file)
|
||||
{
|
||||
if (file == null || file.ContentLength <= 0)
|
||||
{
|
||||
throw new ArgumentException("文件为空的。");
|
||||
}
|
||||
if (!IsValidation(file))
|
||||
{ throw new ArgumentException("无效的文件类型。"); }
|
||||
|
||||
string storepath = Sliced ? (string.IsNullOrWhiteSpace(ResumableInfo.StorePath) ? (ResumableInfo.StorePath = CreateStorePath()) : ResumableInfo.StorePath)
|
||||
: CreateStorePath()
|
||||
, physicalPath = Context.Server.MapPath("~" + storepath),dir = Path.GetDirectoryName(physicalPath);
|
||||
if (!Directory.Exists(dir)){Directory.CreateDirectory(dir);}
|
||||
if (Sliced)
|
||||
{
|
||||
|
||||
using (BinaryWriter bw = new BinaryWriter(new FileStream(physicalPath, FileMode.Append, FileAccess.Write, FileShare.Read)))
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
while (0 < file.InputStream.Read(buffer, 0, buffer.Length))
|
||||
{
|
||||
bw.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
bw.Flush();
|
||||
}
|
||||
ResumableInfo.BlobIndex = ResumableInfo.BlobIndex + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.SaveAs(physicalPath);
|
||||
}
|
||||
return Sliced ? new FileUploadComplete(storepath, FileSize, Sliced, ResumableInfo.BlobIndex, ResumableInfo.BlobCount)
|
||||
: new FileUploadComplete(storepath, file.ContentLength, null);
|
||||
}
|
||||
protected virtual void DeleteResumable(Guid? key = null)
|
||||
{
|
||||
var k = key ?? ResumableKey;
|
||||
var info = Provider.GetResumableInfo(k);
|
||||
if (info != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.StorePath))
|
||||
{
|
||||
string physicalPath = Context.Server.MapPath("~" + info.StorePath);
|
||||
if (File.Exists(physicalPath)) { File.Delete(physicalPath); }
|
||||
}
|
||||
RemoveResumableInfo(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Html5Uploader/Html5Uploader.csproj
Normal file
79
Html5Uploader/Html5Uploader.csproj
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{07F2A054-679A-4AA7-8C78-DAFEBF6D2EEF}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Html5Uploader</RootNamespace>
|
||||
<AssemblyName>Html5Uploader</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.3.0.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>L:\学习\编程类\C#\DLL\html解析器\HtmlAgilityPack.1.4.6\Net40\HtmlAgilityPack.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controls\Enums.cs" />
|
||||
<Compile Include="Controls\PostParametersCollection.cs" />
|
||||
<Compile Include="Controls\ClientEventsCollection.cs" />
|
||||
<Compile Include="Controls\ViewTemplate.cs" />
|
||||
<Compile Include="FilesUploadHandler.cs" />
|
||||
<Compile Include="FileUploadComplete.cs" />
|
||||
<Compile Include="ResumableInfo.cs" />
|
||||
<Compile Include="ResumableInfoProvider.cs" />
|
||||
<Compile Include="ResumableInfoXmlManager.cs" />
|
||||
<Compile Include="SlicedSet.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Controls\Html5UploaderClient.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Controls\Uploader.release.min.js" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Helper\Helper.csproj">
|
||||
<Project>{6c6c0829-dfb5-4ae1-b763-7803d23e17e9}</Project>
|
||||
<Name>Helper</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
38
Html5Uploader/Properties/AssemblyInfo.cs
Normal file
38
Html5Uploader/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Web.UI;
|
||||
|
||||
// 有关程序集的常规信息通过以下
|
||||
// 特性集控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("Html5Uploader")]
|
||||
[assembly: AssemblyDescription("Jackson.bruce@live.com 技术支持")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Jackson.bruce")]
|
||||
[assembly: AssemblyProduct("Html5Uploader")]
|
||||
[assembly: AssemblyCopyright("© 2014 Jackson.bruce")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 使此程序集中的类型
|
||||
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
|
||||
// 则将该类型上的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("90fbfcff-11fc-43a3-8f1c-0ede65ff2539")]
|
||||
|
||||
// 程序集的版本信息由下面四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: WebResource("Html5Uploader.Controls.Uploader.release.min.js", "application/x-javascript")]
|
||||
64
Html5Uploader/ResumableInfo.cs
Normal file
64
Html5Uploader/ResumableInfo.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Html5Uploader
|
||||
{
|
||||
public class ResumableInfo
|
||||
{
|
||||
public ResumableInfo(string FileName
|
||||
, string FileType
|
||||
, string StorePath
|
||||
, long FileSize
|
||||
, long BlobSize
|
||||
, long BlobCount
|
||||
, Guid? Key=null
|
||||
, long BlobIndex=0
|
||||
, DateTime? CreateDate=null)
|
||||
{
|
||||
this.StorePath = StorePath;
|
||||
this.Key = Key ?? Guid.NewGuid();
|
||||
this.FileName = FileName;
|
||||
this.FileType = FileType;
|
||||
this.FileSize = FileSize;
|
||||
this.BlobSize = BlobSize;
|
||||
this.BlobCount = BlobCount;
|
||||
this.BlobIndex = BlobIndex;
|
||||
this.CreateDate = CreateDate ?? DateTime.Now;
|
||||
}
|
||||
public Guid Key { get;protected set; }
|
||||
/// <summary>
|
||||
/// 文件名称
|
||||
/// </summary>
|
||||
public string FileName { get; protected set; }
|
||||
/// <summary>
|
||||
/// 文件类型
|
||||
/// </summary>
|
||||
public string FileType { get; protected set; }
|
||||
/// <summary>
|
||||
/// 存储位置
|
||||
/// </summary>
|
||||
public string StorePath { get; set; }
|
||||
/// <summary>
|
||||
/// 文件大小
|
||||
/// </summary>
|
||||
public long FileSize { get; protected set; }
|
||||
/// <summary>
|
||||
/// 切片大小
|
||||
/// </summary>
|
||||
public long BlobSize { get; protected set; }
|
||||
/// <summary>
|
||||
/// 切片总数
|
||||
/// </summary>
|
||||
public long BlobCount { get; protected set; }
|
||||
/// <summary>
|
||||
/// 已经完成的切片索引
|
||||
/// </summary>
|
||||
public long BlobIndex { get; set; }
|
||||
/// <summary>
|
||||
/// 创建的时间
|
||||
/// </summary>
|
||||
public DateTime CreateDate { get; protected set; }
|
||||
}
|
||||
}
|
||||
17
Html5Uploader/ResumableInfoProvider.cs
Normal file
17
Html5Uploader/ResumableInfoProvider.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Html5Uploader
|
||||
{
|
||||
public abstract class ResumableInfoProvider:IDisposable
|
||||
{
|
||||
public abstract IEnumerable<ResumableInfo> ResumableInfos { get; }
|
||||
public abstract ResumableInfo GetResumableInfo(Guid key);
|
||||
public abstract ResumableInfo GetResumableInfo(string fileName, string fileType, long fileSize, long blobSize, long blobCount);
|
||||
public abstract void SaveResumableInfo(ResumableInfo info);
|
||||
public abstract void DeleteResumableInfo(Guid key);
|
||||
public abstract void Dispose();
|
||||
}
|
||||
}
|
||||
199
Html5Uploader/ResumableInfoXmlManager.cs
Normal file
199
Html5Uploader/ResumableInfoXmlManager.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Configuration;
|
||||
using System.IO;
|
||||
using System.Xml.Linq;
|
||||
namespace Html5Uploader
|
||||
{
|
||||
public class ResumableInfoXmlProvider : ResumableInfoProvider
|
||||
{
|
||||
static object lockObject = new object();
|
||||
public ResumableInfoXmlProvider() {}
|
||||
protected virtual string ElementName{
|
||||
get {
|
||||
return "resumable";
|
||||
}
|
||||
}
|
||||
protected virtual string GetStorePath()
|
||||
{
|
||||
string p = (WebConfigurationManager.AppSettings["Html5Uploader:StorePath"] ?? "").Trim().Replace('\\','/');
|
||||
if (0==p.Length)
|
||||
{
|
||||
p = "~/config/ResumableFilesStore.xml";
|
||||
}
|
||||
else {
|
||||
if (p.StartsWith("/"))
|
||||
{
|
||||
p = "~" + p;
|
||||
}
|
||||
else if(!p.StartsWith("~/")) {
|
||||
p = Path.Combine("~/", p);
|
||||
}
|
||||
}
|
||||
|
||||
p = HttpContext.Current.Server.MapPath(p);
|
||||
return p;
|
||||
|
||||
}
|
||||
protected virtual void UpdateElement(ResumableInfo info,XElement e)
|
||||
{
|
||||
|
||||
e.Attr("key", info.Key);
|
||||
e.Attr("fileName",info.FileName);
|
||||
e.Attr("fileType",info.FileType);
|
||||
e.Attr("storePath",info.StorePath);
|
||||
e.Attr("fileSize",info.FileSize);
|
||||
e.Attr("blobSize",info.BlobSize);
|
||||
e.Attr("blobCount",info.BlobCount);
|
||||
e.Attr("blobIndex",info.BlobIndex);
|
||||
e.Attr("createDate", info.CreateDate);
|
||||
|
||||
}
|
||||
|
||||
IEnumerable<ResumableInfo> _resumableInfos;
|
||||
public override IEnumerable<ResumableInfo> ResumableInfos
|
||||
{
|
||||
get {
|
||||
if (_resumableInfos == null)
|
||||
{
|
||||
string key= "Html5Uploader.ResumableInfoXmlManager.ResumableInfos";
|
||||
_resumableInfos = HttpRuntime.Cache[key] as IEnumerable<ResumableInfo>;
|
||||
if (_resumableInfos == null)
|
||||
{
|
||||
XDocument doc;
|
||||
string store=GetStorePath();
|
||||
lock (lockObject)
|
||||
{
|
||||
if (File.Exists(store))
|
||||
{
|
||||
doc = XDocument.Load(store);
|
||||
}
|
||||
else
|
||||
{
|
||||
doc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement(ElementName + "s"));
|
||||
string dir = Path.GetDirectoryName(store);
|
||||
if (!Directory.Exists(dir))
|
||||
{ Directory.CreateDirectory(dir); }
|
||||
doc.Save(store);
|
||||
}
|
||||
}
|
||||
_resumableInfos = (from n in doc.Root.Elements(ElementName)
|
||||
let item = new ResumableInfo(n.Attr("fileName")
|
||||
, n.Attr("fileType")
|
||||
, n.Attr("storePath")
|
||||
, n.Attr<long>("fileSize")
|
||||
, n.Attr<long>("blobSize")
|
||||
, n.Attr<long>("blobCount")
|
||||
, n.AttrStruct<Guid>("key")
|
||||
, n.Attr<long>("blobIndex")
|
||||
, n.Attr<DateTime>("createDate"))
|
||||
where item.Key != Guid.Empty
|
||||
select item).ToArray();
|
||||
HttpRuntime.Cache.Insert(key, _resumableInfos
|
||||
, new CacheDependency(store)
|
||||
, Cache.NoAbsoluteExpiration, TimeSpan.FromHours(1));
|
||||
}
|
||||
}
|
||||
return _resumableInfos;
|
||||
}
|
||||
|
||||
}
|
||||
public override ResumableInfo GetResumableInfo(Guid key)
|
||||
{
|
||||
foreach (var e in ResumableInfos)
|
||||
{
|
||||
if (e.Key == key)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public override ResumableInfo GetResumableInfo(string fileName, string fileType, long fileSize, long blobSize, long blobCount)
|
||||
{
|
||||
foreach (var e in ResumableInfos)
|
||||
{
|
||||
if (string.Equals(e.FileName, fileName, StringComparison.CurrentCultureIgnoreCase)
|
||||
&& e.FileSize == fileSize
|
||||
&& e.BlobSize == blobSize
|
||||
&& e.BlobCount == blobCount
|
||||
//如果类型是空的,那么智能忽略,否则同时比较类型
|
||||
&& (string.IsNullOrWhiteSpace(e.FileType) || string.IsNullOrWhiteSpace(fileType) || string.Equals(e.FileType, fileType, StringComparison.CurrentCultureIgnoreCase))
|
||||
)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public override void SaveResumableInfo(ResumableInfo info)
|
||||
{
|
||||
XDocument doc;
|
||||
XElement e =null;
|
||||
//启动线程保护,防止多个线程同时写入文件
|
||||
lock (lockObject)
|
||||
{
|
||||
string store = GetStorePath();
|
||||
if (File.Exists(store))
|
||||
{
|
||||
doc = XDocument.Load(store);
|
||||
var xe = from x in doc.Root.Elements(ElementName) select x;
|
||||
foreach (var x in xe)
|
||||
{
|
||||
if (x.Attr<Guid>("key") == info.Key)
|
||||
{
|
||||
e = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (e == null)
|
||||
{
|
||||
e = new XElement(ElementName);
|
||||
doc.Root.Add(e);
|
||||
}
|
||||
UpdateElement(info, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new XElement(ElementName);
|
||||
UpdateElement(info, e);
|
||||
doc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement(ElementName + "s", e));
|
||||
string dir = Path.GetDirectoryName(store);
|
||||
if (!Directory.Exists(dir))
|
||||
{ Directory.CreateDirectory(dir); }
|
||||
}
|
||||
doc.Save(store);
|
||||
}
|
||||
}
|
||||
public override void DeleteResumableInfo(Guid key)
|
||||
{
|
||||
string store = GetStorePath();
|
||||
//启动线程保护,防止多个线程同时写入文件
|
||||
lock (lockObject)
|
||||
{
|
||||
if (File.Exists(store))
|
||||
{
|
||||
XDocument doc = XDocument.Load(store);
|
||||
var xe = (from x in doc.Root.Elements(ElementName) select x).ToArray();
|
||||
foreach (var x in xe)
|
||||
{
|
||||
if (x.Attr<Guid>("key") == key)
|
||||
{
|
||||
x.Remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
doc.Save(store);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Html5Uploader/SlicedSet.cs
Normal file
17
Html5Uploader/SlicedSet.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Html5Uploader
|
||||
{
|
||||
public enum SlicedSet
|
||||
{
|
||||
Auto = 0
|
||||
,
|
||||
Enabled=1
|
||||
,
|
||||
Disabled =2
|
||||
}
|
||||
}
|
||||
132
Uploader/HTML5UploaderWebSiteTest.csproj
Normal file
132
Uploader/HTML5UploaderWebSiteTest.csproj
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{152482F9-A932-4C5A-914F-F7D646921286}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>HTML5Uploader</RootNamespace>
|
||||
<AssemblyName>HTML5UploaderWebSiteTest</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<TargetFrameworkProfile />
|
||||
<UseGlobalApplicationHostFile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Html5Uploader, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>bin\Html5Uploader.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.DynamicData" />
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.EnterpriseServices" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Web.Release.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="index.aspx" />
|
||||
<Content Include="index.html" />
|
||||
<Content Include="packages.config" />
|
||||
<Content Include="Handler1.ashx" />
|
||||
<None Include="Scripts\jquery-2.1.1.intellisense.js" />
|
||||
<Content Include="Scripts\jquery-2.1.1.js" />
|
||||
<Content Include="Scripts\jquery-2.1.1.min.js" />
|
||||
<Content Include="Scripts\Uploader.js" />
|
||||
<Content Include="Web.config" />
|
||||
<Content Include="Scripts\jquery-2.1.1.min.map" />
|
||||
<Content Include="Scripts\Uploader.Release.js" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Handler1.ashx.cs">
|
||||
<DependentUpon>Handler1.ashx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="index.aspx.cs">
|
||||
<DependentUpon>index.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="index.aspx.designer.cs">
|
||||
<DependentUpon>index.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>53119</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:53119/</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
1
Uploader/Handler1.ashx
Normal file
1
Uploader/Handler1.ashx
Normal file
@@ -0,0 +1 @@
|
||||
<%@ WebHandler Language="C#" CodeBehind="Handler1.ashx.cs" Class="HTML5Uploader.Handler1" %>
|
||||
224
Uploader/Handler1.ashx.cs
Normal file
224
Uploader/Handler1.ashx.cs
Normal file
@@ -0,0 +1,224 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
|
||||
namespace HTML5Uploader
|
||||
{
|
||||
/// <summary>
|
||||
/// Handler1 的摘要说明
|
||||
/// </summary>
|
||||
public class Handler1 : Html5Uploader.FilesUploadHandler
|
||||
{
|
||||
//object LockObject = new object();
|
||||
//static List<byte[]> Data;
|
||||
|
||||
//public void ProcessRequest(HttpContext context)
|
||||
//{
|
||||
// ////bool sliced;
|
||||
// ////bool.TryParse(context.Request.Form["sliced"], out sliced);
|
||||
// ////var files = context.Request.Files;
|
||||
// ////if (files != null && files.Count > 0)
|
||||
// ////{
|
||||
// //// var file = files[0];
|
||||
// //// string name =sliced? Path.GetFileName(file.FileName):context.Request.Form["name"], tempFilePath = context.Server.MapPath("~/" + name);
|
||||
// //// if (sliced)
|
||||
// //// {
|
||||
// //// byte[] buffer = new byte[file.InputStream.Length];
|
||||
// //// file.InputStream.Read(buffer, 0, buffer.Length);
|
||||
// //// using (BinaryWriter bw = new BinaryWriter(new FileStream(tempFilePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
|
||||
// //// {
|
||||
// //// bw.Write(buffer, 0, buffer.Length);
|
||||
// //// bw.Flush();
|
||||
// //// }
|
||||
// //// }
|
||||
// //// else {
|
||||
|
||||
// //// }
|
||||
// ////}
|
||||
// context.Response.Write("{index:100,key:'" + Guid.NewGuid() + "'}");
|
||||
//}
|
||||
////void v2()
|
||||
////{
|
||||
|
||||
//// //var files = context.Request.Files;
|
||||
//// //if (files != null && files.Count > 0)
|
||||
//// //{
|
||||
//// // long count;
|
||||
//// // int index;
|
||||
//// // long.TryParse(context.Request.Form["count"], out count);
|
||||
//// // int.TryParse(context.Request.Form["index"], out index);
|
||||
//// // lock (LockObject)
|
||||
//// // {
|
||||
//// // if (Data == null)
|
||||
//// // {
|
||||
//// // Data = new List<byte[]>(new byte[count][]);
|
||||
//// // }
|
||||
//// // }
|
||||
//// // var file = files[0];
|
||||
//// // byte[] buffer = new byte[file.InputStream.Length];
|
||||
//// // file.InputStream.Read(buffer, 0, buffer.Length);
|
||||
//// // lock (Data)
|
||||
//// // {
|
||||
//// // Data[index] = buffer;
|
||||
//// // }
|
||||
//// // if (index >= count - 1)
|
||||
//// // {
|
||||
//// // string name = context.Request.Form["name"], tempFilePath = context.Server.MapPath("~/" + name);
|
||||
//// // lock (LockObject)
|
||||
//// // {
|
||||
//// // var arr = Data.ToArray();
|
||||
//// // for (int i = 0; i < arr.Length; i++)
|
||||
//// // {
|
||||
//// // var d = arr[i];
|
||||
//// // using (BinaryWriter bw = new BinaryWriter(new FileStream(tempFilePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
|
||||
//// // {
|
||||
//// // bw.Write(d, 0, d.Length);
|
||||
//// // bw.Flush();
|
||||
//// // }
|
||||
//// // }
|
||||
//// // Data = null;
|
||||
//// // }
|
||||
//// // }
|
||||
|
||||
//// //}
|
||||
////}
|
||||
////void temp(HttpContext context)
|
||||
////{
|
||||
//// string name = context.Request.Form["name"], tempFilePath = context.Server.MapPath("~/" + name);
|
||||
//// var files = context.Request.Files;
|
||||
//// long loaded, total, position;
|
||||
//// long.TryParse(context.Request.Form["loaded"], out loaded);
|
||||
//// long.TryParse(context.Request.Form["position"], out position);
|
||||
//// if (files != null && files.Count > 0)
|
||||
//// {
|
||||
//// long.TryParse(context.Request.Form["total"], out total);
|
||||
//// FileResumer fr = new FileResumer();
|
||||
//// fr.m_FileSize = total;
|
||||
//// fr.RangePos = position;
|
||||
//// var file = files[0];
|
||||
//// loaded += file.InputStream.Length;
|
||||
|
||||
//// fr.Resumer(ref file, tempFilePath);
|
||||
//// //using (BinaryWriter bw = new BinaryWriter(new FileStream(tempFilePath, FileMode.Append, FileAccess.Write,FileShare.ReadWrite)))
|
||||
//// //{
|
||||
//// // using (BinaryReader br = new BinaryReader(files[0].InputStream))
|
||||
//// // {
|
||||
//// // var arr = new byte[br.BaseStream.Length];
|
||||
//// // br.Read(arr, 0, arr.Length);
|
||||
//// // bw.Write(arr, 0,arr.Length);
|
||||
//// // //var arr = new byte[1024];
|
||||
//// // //while (br.Read(arr, 0, arr.Length) > 0)
|
||||
//// // //{
|
||||
//// // // bw.Write(arr, 0, arr.Length);
|
||||
//// // //}
|
||||
//// // }
|
||||
//// // bw.Flush();
|
||||
//// //}
|
||||
//// }
|
||||
//// context.Response.Write("{loaded:" + loaded + "}");
|
||||
//// //context.Response.Write(Convert.ToBase64String(Encoding.UTF8.GetBytes("kkkkkkkk")));
|
||||
//// //context.Response.Write(Encoding.UTF8.GetString(Convert.FromBase64String("a2tra2tra2s=")));
|
||||
////}
|
||||
////async void Write(byte[] data, string tempFilePath)
|
||||
////{
|
||||
//// long sPosstion;
|
||||
//// FileStream FStream;
|
||||
//// if (File.Exists(tempFilePath))
|
||||
//// {
|
||||
//// FStream = File.OpenWrite(tempFilePath);
|
||||
//// sPosstion = FStream.Length;
|
||||
//// FStream.Seek(sPosstion, SeekOrigin.Current);//移动文件流中的当前指针
|
||||
//// }
|
||||
//// else
|
||||
//// {
|
||||
//// FStream = new FileStream(tempFilePath, FileMode.Create);
|
||||
//// sPosstion = 0;
|
||||
//// }
|
||||
//// await FStream.WriteAsync(data, 0, data.Length);
|
||||
//// FStream.Close();
|
||||
//// FStream.Dispose();
|
||||
////}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 文件续传类
|
||||
/// </summary>
|
||||
public class FileResumer
|
||||
{
|
||||
public long m_FileSize; //文件总大小。
|
||||
string m_FileMD5; //
|
||||
long m_RangePos; //文件块起始位置
|
||||
public long RangePos
|
||||
{
|
||||
set { this.m_RangePos = value; }
|
||||
}
|
||||
int m_RangeSize; //文件块大小
|
||||
|
||||
//文件读写锁,防止多个用户同时上传相同文件时,出现创建文件的错误
|
||||
static ReaderWriterLock m_writeLock = new ReaderWriterLock();
|
||||
|
||||
public FileResumer()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据文件大小创建文件。
|
||||
/// 注意:多个用户同时上传相同文件时,可能会同时创建相同文件。
|
||||
/// </summary>
|
||||
public void CreateFile(string filePath)
|
||||
{
|
||||
//文件不存在则创建
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
//创建文件
|
||||
//这里存在多个线程同时创建文件的问题。
|
||||
FileStream fs = File.OpenWrite(filePath);
|
||||
BinaryWriter w = new BinaryWriter(fs);
|
||||
for (long i = 0; i < this.m_FileSize; ++i)
|
||||
{
|
||||
w.Write((byte)0);
|
||||
}
|
||||
w.Close();
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续传文件
|
||||
/// </summary>
|
||||
/// <param name="fileRange">文件块</param>
|
||||
/// <param name="fileRemote">远程文件完整路径。d:\www\web\upload\201204\10\md5.exe</param>
|
||||
public void Resumer(ref HttpPostedFile fileRange, string fileRemote)
|
||||
{
|
||||
//存在多个用户同时创建相同文件的问题。
|
||||
m_writeLock.AcquireWriterLock(1000);
|
||||
this.CreateFile(fileRemote);
|
||||
m_writeLock.ReleaseWriterLock();
|
||||
|
||||
//上传的文件大小不为空
|
||||
if (fileRange.InputStream.Length > 0)
|
||||
{
|
||||
//文件已存在,写入数据
|
||||
//可能会有多个线程同时写文件。
|
||||
FileStream fs = new FileStream(fileRemote, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
|
||||
fs.Seek(this.m_RangePos, SeekOrigin.Begin);
|
||||
byte[] ByteArray = new byte[fileRange.InputStream.Length];
|
||||
fileRange.InputStream.Read(ByteArray, 0, (int)fileRange.InputStream.Length);
|
||||
fs.Write(ByteArray, 0, (int)fileRange.InputStream.Length);
|
||||
fs.Flush();
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
35
Uploader/Properties/AssemblyInfo.cs
Normal file
35
Uploader/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的常规信息通过下列特性集
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("HTML5Uploader")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("HTML5Uploader")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
// 对 COM 组件不可见。如果需要
|
||||
// 从 COM 访问此程序集中的某个类型,请针对该类型将 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于 typelib 的 ID
|
||||
[assembly: Guid("a9dcad6a-f5ef-4bbf-97ad-35ced6e15b8c")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 内部版本号
|
||||
// 修订版本
|
||||
//
|
||||
// 可以指定所有值,也可以使用“修订号”和“内部版本号”的默认值,
|
||||
// 方法是按如下所示使用 "*":
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
550
Uploader/Scripts/Uploader.Release.js
Normal file
550
Uploader/Scripts/Uploader.Release.js
Normal file
@@ -0,0 +1,550 @@
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
|
||||
//公开方法与构造函数
|
||||
//实例化一个上传器,参数settings说明:
|
||||
//object类型:{...}
|
||||
// placeholder:"#btnSelectFiles"//打开文件选择器的占位符,可选的类型:jQuery对象或者字符串类型的jQuery选择器
|
||||
// multiple:true //文件选择器对话框是否支持多选,默认值true
|
||||
// accept:"image/*,text/xml" //接受的文件类型,默认值是空的,即是接受全部类型
|
||||
// dragable:false 可以拖拽文件上传,默认是未开启的
|
||||
// dragContainer:"#container" 拖拽入的容器,可选的类型:jQuery对象或者字符串类型的jQuery选择器
|
||||
// progress:"#box" //文件上传进度列表容器,可选的类型:jQuery对象或者字符串类型的jQuery选择器
|
||||
// blobSize:number //文件切片上传时,单个数据块的大小,单位是字节
|
||||
// sliced:number //是否支持切片上传,可用值:Uploader.Sliced.Auto(0),Uploader.Sliced.Enabled(1),Uploader.Sliced.Disabled(2) 默认值 Uploader.Sliced.Auto
|
||||
// limitSize:number //上传文件大小限制,单位是字节,默认值0 表示没有限制
|
||||
// url:"/fileUpload/handler" //服务端的处理程序,默认值是当前浏览器的地址(location.href)
|
||||
// params:{...} //和文件一起提交到服务端的自定义参数,object类型
|
||||
// parseResult //这个是个函数用来解析服务端返回的结果集 function(serverData) 返回值是object,如果服务端有错误应该返回{err:true,msg:“错误描述”}的对象
|
||||
var u = window.Uploader = function (settings, events) {
|
||||
|
||||
if (!(this instanceof u)) { return new u(settings, events) };
|
||||
var s = this
|
||||
, opts = settings || {}
|
||||
, context = { events: {}, files: [] }
|
||||
, sltfsfn = s.upload = function (files) {
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
selecting.apply(s, [files[i], context])
|
||||
}
|
||||
};
|
||||
|
||||
s.version = u.Version;
|
||||
//检查浏览器支持
|
||||
s.support = u.Support;
|
||||
if (!s.support) return false;
|
||||
|
||||
//读取设置
|
||||
s.settings = function (n) {
|
||||
var v = opts[n];
|
||||
return typeof (v) === udfs ? defaultSettings[n] : v;
|
||||
};
|
||||
if (typeof (opts.params) === udfs) { opts.params = {} }
|
||||
if (typeof (opts.types) == "string") { context.types = opts.types.split(';') }
|
||||
|
||||
//事件绑定 可用事件:
|
||||
//selecting 选择文件 function(file,args) args:{ cancel: false,invalidType:false||true }
|
||||
//selected 已经选择了文件 function(file)
|
||||
//upload 开始上传文件 function(file,args) args:{cancel: false}
|
||||
//createProgress 创建进度视图 function(file,args) args:{view:null} args.view:返回已经创建的视图
|
||||
//getResumableInfoHandler 获取续传信息时触发 function(url,params,callback) url:服务端处理程序,params:文件参数 {fileType:string,fileName:string,fileSize:number,blobSize: number,blobCount:number} callback:function(ResumableInfo:{key,index}) 回调函数
|
||||
//progress 更新进度视图 function(file,args) args: {view:当前视图,cancel: false,size :文件大小,loaded:已经上传的大小,percent:0 ~ 100}
|
||||
//complete 文件上传完成 function(file,args) args:{view:当前视图, req: XMLHttpRequest, status:XMLHttpRequest.status}
|
||||
//success 文件上传成功 function(file,args) args:{view:当前视图,responseText: XMLHttpRequest.responseText,cancel: false, req:XMLHttpRequest,responseType: XMLHttpRequest.responseType, responseXML:XMLHttpRequest.responseXML}
|
||||
//error 错误处理 function(file,args) args:{ view: 当前视图,type:Uploader.ErrorType,code:number,message:string }
|
||||
//drop 启动拖拽上传时(dragable=true)在拖拽容器上拖拽时触发的事件
|
||||
//dragover 启动拖拽上传时(dragable=true)在拖拽容器上拖拽时触发的事件
|
||||
//dragleave 启动拖拽上传时(dragable=true)从拖拽容器上拽出时触发的事件
|
||||
|
||||
s.on = function (a) {
|
||||
var args = arguments;
|
||||
if (args.length == 2) { setHandlers(args[0], context.events, args[1]) }
|
||||
else if (a) {
|
||||
for (var n in a) { setHandlers(n, context.events, a[n]) }
|
||||
}
|
||||
};
|
||||
if (events) { s.on(events) }
|
||||
var multiple = s.settings("multiple"), accept = s.settings("accept"), fs;
|
||||
//
|
||||
if (opts.placeholder) {
|
||||
var btn = $(opts.placeholder), fileSelector;
|
||||
fs = btn.find("[type='file']");
|
||||
if (!fs.length) {
|
||||
fs = $(fileSelector = document.createElement("input")).attr("type", "file").css({ display: 'none', opacity: 0 }).appendTo(btn)
|
||||
} else { fileSelector = fs[0] }
|
||||
btn.click(function () { fileSelector.click() });
|
||||
if (multiple) { fs.attr("multiple", "multiple") }
|
||||
if (accept) { fs.attr("accept", accept) }
|
||||
fs.change(function () { sltfsfn(this.files) })
|
||||
}
|
||||
//else {
|
||||
// fs = $("input[type='file']")//.on("change", function () { sltfsfn(this.files) });
|
||||
//}
|
||||
if (s.settings("dragable") || !opts.placeholder) {
|
||||
var drp = s.settings("dragContainer"), defaultDragContainerFlag = false;
|
||||
if (!drp) {
|
||||
defaultDragContainerFlag = true;
|
||||
drp = $(document.createElement("div")).attr("data-default-dragContainer", defaultDragContainerFlag).css({ display: "none", position: "fixed", "z-index": 9999999, top: 0, left: 0, bottom: 0, right: 0, opacity: 0 }).appendTo("body")
|
||||
}
|
||||
else if (!(drp instanceof jQuery)) { drp = $(drp) }
|
||||
if (drp.length) {
|
||||
var dr = drp[0]
|
||||
, dragEnterfn = function (e) {
|
||||
e.preventDefault();
|
||||
if (defaultDragContainerFlag) { clearTimeout(dr.time); dr.time = null; drp.show() }
|
||||
else { drp.addClass("over") }
|
||||
}
|
||||
, dragLeavefn = function (e) {
|
||||
e.preventDefault();
|
||||
if (defaultDragContainerFlag) {
|
||||
if (!dr.time)
|
||||
{ dr.time = setTimeout(function () { drp.hide() }, 10) }
|
||||
}
|
||||
else { drp.removeClass("over") }
|
||||
};
|
||||
|
||||
|
||||
$(document).on({
|
||||
dragleave: dragLeavefn,
|
||||
drop: function (e) {
|
||||
e.preventDefault();
|
||||
drp.removeClass("over")
|
||||
},
|
||||
dragenter: dragEnterfn,
|
||||
dragover: dragEnterfn
|
||||
});
|
||||
dr.addEventListener("dragleave", function (e) {
|
||||
triggerEvents("dragleave", context, function (fn) { fn.call(s, e) })
|
||||
}, false);
|
||||
dr.addEventListener("dragover", function (e) {
|
||||
e = e || window.event;
|
||||
e.stopPropagation();
|
||||
dragEnterfn(e);
|
||||
triggerEvents("dragover", context, function (fn) { fn.call(s, e) });
|
||||
//e.dataTransfer.dropEffect = 'copy' //指定拖放视觉效果
|
||||
}, false);
|
||||
dr.addEventListener("drop", function (e) {
|
||||
e = e || window.event;
|
||||
e.stopPropagation();
|
||||
dragLeavefn(e);
|
||||
//获取文件列表
|
||||
var files = e.dataTransfer ? e.dataTransfer.files : null;
|
||||
e.cancel = false;
|
||||
triggerEvents("drop", context, function (fn) { fn.call(s, e) });
|
||||
if (!e.cancel && files && files.length) { sltfsfn(files) }
|
||||
}, false)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
, udfs = 'undefined';
|
||||
//静态属性和方法
|
||||
u.Version = { major: 1, minor: 0, revision: 0 };
|
||||
u.Version.toString = function () { return this.major + "." + this.minor + "." + this.revision };
|
||||
//检查浏览器支持
|
||||
u.Support = typeof (window.File) !== udfs && typeof (window.FileList) !== udfs && (typeof (window.Blob) === "function" &&
|
||||
(!!window.Blob.prototype.webkitSlice || !!window.Blob.prototype.mozSlice || !!window.Blob.prototype.slice || false));
|
||||
u.Sliced = { Auto: 0, Enabled: 1, Disabled: 2 };
|
||||
u.ErrorType = {
|
||||
//无效的文件类型
|
||||
InvalidType: 0
|
||||
,
|
||||
//超过文件上限
|
||||
UpperLimit: 1
|
||||
,
|
||||
HttpType: 2
|
||||
,
|
||||
ServerType: 3
|
||||
,
|
||||
UserAbort: 4
|
||||
,
|
||||
InvalidOperation: 5
|
||||
};
|
||||
u.SizeToString = function (size, num) {
|
||||
if (typeof (size) !== "number") return size;
|
||||
var unit = "byte", units = ["KB", "MB", "GB", "TB"], l = 1024, fn = function (n) {
|
||||
if (size > l) {
|
||||
size = size / l;
|
||||
unit = n;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (var i = 0; i < units.length; i++)
|
||||
{ if (!fn(units[i])) break }
|
||||
l = Math.pow(10, (typeof (num) !== "number" || num <= 0 ? 3 : num));
|
||||
return (Math.round(size * l) / l) + unit
|
||||
};
|
||||
//默认配置
|
||||
var defaultSettings = {
|
||||
url: location.href
|
||||
, multiple: true
|
||||
///默认是3MB
|
||||
, blobSize: 1024 * 1024 * 3
|
||||
, sliced: u.Sliced.Auto
|
||||
, dragable: false
|
||||
};
|
||||
//私有方法
|
||||
function isValidType(file, context) {
|
||||
var s = this, n = file.name, did = false, args = { invalid: true, accept: s.settings("accept"), types: context.types };
|
||||
triggerEvents("validate", context, function (fn) { fn.call(s, file, args); did = true });
|
||||
if (did) { return !args.invalid }
|
||||
if (!context.types) return true;
|
||||
for (var i = 0; i < context.types.length; i++) {
|
||||
var o = $.trim(context.types[i]);
|
||||
if (!o) continue;
|
||||
if (new RegExp(escape(o) + "$", "i").test(n)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function setHandlers(n, e, fn) {
|
||||
if (typeof (n) !== "string" || typeof (fn) !== "function") return;
|
||||
var h = e[n = n.toUpperCase()];
|
||||
if (!h) { h = e[n] = [] }
|
||||
h.push(fn)
|
||||
|
||||
}
|
||||
function getHandlers(n, e) {
|
||||
return typeof (n) === "string" && e ? e[n.toUpperCase()] : null
|
||||
}
|
||||
function triggerEvents(n, c, b) {
|
||||
var h = getHandlers(n, c.events);
|
||||
if (h) {
|
||||
for (var i = 0; i < h.length; i++) {
|
||||
var fn = h[i];
|
||||
if (typeof (fn) === "function") {
|
||||
try { b(fn) } catch (x) { console.log(x, fn) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//事件
|
||||
function error(file, context, args, msg) {
|
||||
var s = this;
|
||||
s.hasError = true;
|
||||
s.error = args;
|
||||
triggerEvents("error", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) {
|
||||
if (msg = msg || args.message) { s.view.append("<span class='err-info'>" + msg + "</span>") }
|
||||
setTimeout(function () { s.view.remove() }, 5000)
|
||||
}
|
||||
next(context);
|
||||
}
|
||||
function selected(file, context) {
|
||||
var s = this, prog = new Progress(s, file, context);
|
||||
triggerEvents("selected", context, function (fn) { fn.call(s, file) });
|
||||
if (!context.progress) { context.progress = [] }
|
||||
context.progress.push(prog);
|
||||
upload.call(s, file, context);
|
||||
}
|
||||
function selecting(file, context) {
|
||||
var s = this, args = { cancel: false, invalidType: !isValidType.call(s, file, context) };
|
||||
if (args.invalidType) { file.invalidType = true }
|
||||
triggerEvents("selecting", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) {
|
||||
context.files.push(file);
|
||||
selected.apply(s, [file, context])
|
||||
}
|
||||
}
|
||||
|
||||
function upload(file, context) {
|
||||
var s = this, prs = context.progress, args = { cancel: false, maxQueue: s.settings("maxQueue"), queue: context.queue, lastIndex: context.lastIndex || 0 }
|
||||
, prog = context.progress[args.lastIndex];
|
||||
if (typeof (args.queue) !== "number" || args.queue < 0) { args.queue = 0; }
|
||||
if (args.lastIndex < 0) { args.lastIndex = 0; }
|
||||
if (typeof (args.maxQueue) !== "number" || args.maxQueue < 1) { args.maxQueue = 2; }
|
||||
if (args.queue >= args.maxQueue)
|
||||
{ return }
|
||||
context.queue = args.queue + 1;
|
||||
context.lastIndex = args.lastIndex + 1;
|
||||
args.progress = prog;
|
||||
triggerEvents("upload", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) { prog.proceed() }
|
||||
}
|
||||
function createProgress(file, context) {
|
||||
var s = this, ow = s.owner, args = { view: null };
|
||||
triggerEvents("createProgress", context, function (fn) { fn.call(s, file, args) });
|
||||
if (args.view == null) {
|
||||
//创建默认视图
|
||||
var p = ow.settings("progress");
|
||||
if (!p) {
|
||||
p = ow.settings("dragable") && (p = ow.settings("dragContainer")) && (p = p instanceof jQuery ? p : $(p)).length > 0 ? p : $("body")
|
||||
}
|
||||
//else if (p instanceof jQuery) { p = $(p); }
|
||||
var v = args.view = $(document.createElement("div")).appendTo(p);
|
||||
v.append("<h2>" + file.name + "</h2><p>size:" + u.SizeToString(file.size) + "</p><progress></progress>")
|
||||
}
|
||||
return s.view = args.view
|
||||
}
|
||||
function progress(file, context, st) {
|
||||
var s = this, p, args = { cancel: false, size: s.size, sizeString: u.SizeToString(s.size), view: s.view };
|
||||
if (s.sliced === true) {
|
||||
args.loaded = s.loaded + Math.min(st.currentBlobLoaded, s.blobSize)
|
||||
}
|
||||
else {
|
||||
args.loaded = Math.min(st.currentBlobLoaded, s.size)
|
||||
}
|
||||
p = (args.loaded / args.size) * 100;
|
||||
args.percent = p;
|
||||
args.loadedString = u.SizeToString(args.loaded);
|
||||
triggerEvents("progress", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) {
|
||||
s.bar.attr("value", args.percent)
|
||||
}
|
||||
}
|
||||
function success(file, context, result) {
|
||||
var s = this
|
||||
, args = {
|
||||
view: s.view, cancel: false, result: result
|
||||
, req: s.xhr, responseText: s.xhr.responseText, responseType: s.xhr.responseType, responseXML: s.xhr.responseXML
|
||||
};
|
||||
triggerEvents("success", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) { setTimeout(function () { s.view.remove(); }, 5000) }
|
||||
}
|
||||
function complete(file, context) {
|
||||
var s = this, args = { view: s.view, req: s.xhr, status: s.xhr.status };
|
||||
context.queue--;
|
||||
triggerEvents("complete", context, function (fn) { fn.call(s, file, args) });
|
||||
next(context);
|
||||
}
|
||||
function next(context) {
|
||||
var i = context.lastIndex, s;
|
||||
if (i < context.progress.length) {
|
||||
s = context.progress[i];
|
||||
upload.call(s.owner, s.file, context);
|
||||
}
|
||||
}
|
||||
function Progress(owner, file, context) {
|
||||
this.owner = owner;
|
||||
var s = this, xhr, paused, index = 0, count = 1
|
||||
, size = s.size = file.size
|
||||
, blobSize = s.blobSize = owner.settings("blobSize")
|
||||
, sliced = s.sliced = ((sliced = owner.settings("sliced")) === u.Sliced.Enabled || (sliced === u.Sliced.Auto && size > blobSize) ? true : false)
|
||||
, view = (s.view = createProgress.call(s, file, context) || $())
|
||||
, bar = (s.bar = view.find("progress").attr({ "max": 100, "value": 0 }))
|
||||
, limitSize = owner.settings("limitSize")
|
||||
, url = owner.settings("url")
|
||||
, parseResult = owner.settings("parseResult")
|
||||
, appendParams = function (d) {
|
||||
var ps = owner.settings("params");
|
||||
if (sliced) {
|
||||
d.append("blobIndex", index);
|
||||
d.append("blobCount", count);
|
||||
d.append("resumableKey", s.resumableKey);
|
||||
d.append("sliced", sliced);
|
||||
d.append("fileName", file.name);
|
||||
}
|
||||
d.append("types", owner.settings("types") || "");
|
||||
if (owner.settings("accept")) { d.append("accept", owner.settings("accept")) }
|
||||
for (var p in ps) { d.append(p, ps[p]) }
|
||||
}
|
||||
, send = function (f) {
|
||||
|
||||
xhr.open("post", url, true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
var d = new FormData();
|
||||
d.append("file", f);
|
||||
appendParams(d);
|
||||
//console.log("start:"+new Date().toLocaleTimeString());
|
||||
xhr.send(d)
|
||||
}
|
||||
, sendBlob = function (i) {
|
||||
var start = i * blobSize, end = start + blobSize;
|
||||
index = i;
|
||||
s.loaded = start;
|
||||
if (file.slice) {
|
||||
s.blob = file.slice(start, end);
|
||||
}
|
||||
else if (file.webkitSlice) {
|
||||
s.blob = file.webkitSlice(start, end);
|
||||
} else if (file.mozSlice) {
|
||||
s.blob = file.mozSlice(start, end);
|
||||
}
|
||||
|
||||
|
||||
send(s.blob);
|
||||
};
|
||||
|
||||
if (typeof (parseResult) !== "function") { parseResult = function (d) { var r; try { eval("r=" + d) } catch (e) { r = { err: true, msg: "脚本解析错误。" } } return r } }
|
||||
s.file = file;
|
||||
s.loaded = 0;
|
||||
s.blobSize = blobSize = (sliced ? blobSize : size);
|
||||
s.pause = function () {
|
||||
if (!s.hasError && paused !== true) {
|
||||
s.paused = paused = true;
|
||||
if (xhr && file.uploading === true) {
|
||||
xhr.abort();
|
||||
delete file.uploading;
|
||||
}
|
||||
triggerEvents("pause", context, function (fn) { fn.call(s, file, { view: view }); });
|
||||
context.queue--;
|
||||
next(context);
|
||||
}
|
||||
};
|
||||
s.proceed = function () {
|
||||
if (s.hasError || file.uploading === true) { return; }
|
||||
if (file.uploaded === true || file.canceling === true) {
|
||||
error.call(s, file, context
|
||||
, {
|
||||
type: u.ErrorType.InvalidOperation
|
||||
, message: file.canceling ? "the file is canceling" : file.uploaded ? "the file was uploaded" : "invalid operation", view: view
|
||||
});
|
||||
return
|
||||
}
|
||||
if (paused === true) {
|
||||
var a = { view: view, cancel: false };
|
||||
triggerEvents("proceed", context, function (fn) { fn.call(s, file, a); });
|
||||
if (a.cancel) { return; }
|
||||
}
|
||||
file.cancel = s.paused = paused = false; file.uploading = true;
|
||||
if (!sliced) { send(file); return };
|
||||
var gotit = false
|
||||
, args = { sliced: true, fileType: file.type, fileName: file.name, fileSize: size, blobSize: blobSize, blobCount: count }
|
||||
, b = function (info) {
|
||||
if (info && info.key)
|
||||
{ s.resumableKey = info.key }
|
||||
else { throw new Error(info.msg || info.message || "failed to initialize"); }
|
||||
setTimeout(function () { sendBlob(!isNaN(info.index) ? info.index : 0) }, 0)
|
||||
}
|
||||
, errfn = function (a, x, p) {
|
||||
if (!a) { a = { type: u.ErrorType.ServerType, message: "failed to initialize" } }
|
||||
a.view = view;
|
||||
error.call(s, file, context, a); if (x && x.message) console.log(x.message, p)
|
||||
};
|
||||
triggerEvents("getResumableInfoHandler", context, function (fn) { try { fn.call(s, url, args, b) } catch (x) { errfn(null, x, fn) } gotit = true });
|
||||
if (!gotit) {
|
||||
args.method = "getResumableInfo";
|
||||
|
||||
$.ajax({
|
||||
url: url, type: "POST"
|
||||
, data: args
|
||||
, success: function (d) {
|
||||
var resumable = null;
|
||||
try {
|
||||
eval("resumable=" + d);
|
||||
b(resumable)
|
||||
} catch (x) {
|
||||
//获取初始化信息失败
|
||||
errfn(null, x, d);
|
||||
return
|
||||
}
|
||||
}
|
||||
, error: function (req, txt, dd) {
|
||||
//获取初始化信息失败
|
||||
errfn({ type: u.ErrorType.HttpType, code: req.status, message: txt || errorThrown })
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
s.cancel = function () {
|
||||
if (!s.hasError && file.uploaded !== true && file.cancel !== true && file.canceling !== true) {
|
||||
var doit = function (o) {
|
||||
if (o && !(o.err || o.error)) {
|
||||
file.cancel = true; delete file.canceling; bar.attr("value", 0);
|
||||
triggerEvents("cancel", context, function (fn) { fn.call(s, file, { view: view }) })
|
||||
}
|
||||
};
|
||||
s.pause();
|
||||
file.canceling = true;
|
||||
if (sliced) {
|
||||
$.ajax({
|
||||
url: url, type: "POST", data: { method: "deleteResumable", resumableKey: s.resumableKey }
|
||||
, success: function (d) {
|
||||
var r = null;
|
||||
try {
|
||||
eval("r=" + d);
|
||||
doit(r);
|
||||
} catch (x) {
|
||||
errfn(null, x, d);
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
else { doit(true); }
|
||||
}
|
||||
//
|
||||
};
|
||||
if (file.invalidType || (limitSize && !isNaN(limitSize) && file.size > limitSize)) {
|
||||
error.call(s, file, context
|
||||
, { type: file.invalidType ? u.ErrorType.InvalidType : u.ErrorType.UpperLimit, view: view, message: file.invalidType ? "无效文件类型" : "超过上传限制的大小" }
|
||||
);
|
||||
return
|
||||
}
|
||||
xhr = s.xhr = new XMLHttpRequest();
|
||||
if (typeof (owner.settings("timeout")) === "number") { xhr.timeout = owner.settings("timeout") }
|
||||
|
||||
//事件绑定
|
||||
xhr.addEventListener("readystatechange", function (e) {
|
||||
//完成
|
||||
if (xhr.readyState === 4) {
|
||||
if (s.blob) delete s.blob;
|
||||
var status = xhr.status, isSuccess = status >= 200 && status < 300 || status === 304;
|
||||
if (!isSuccess) {
|
||||
if (paused !== true) { error.call(s, file, context, { type: u.ErrorType.HttpType, code: status, view: view, message: xhr.statusText }) }
|
||||
}
|
||||
if (sliced && index >= count - 1 || !sliced) {
|
||||
if (paused === false) {
|
||||
complete.call(s, file, context);
|
||||
s.paused = paused = true;
|
||||
delete file.uploading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, false);
|
||||
xhr.upload.addEventListener("progress", function (e) {
|
||||
progress.call(s, file, context, { currentBlobLoaded: e.loaded, currentBlobSize: e.total, index: index })
|
||||
}, false);
|
||||
xhr.addEventListener("load", function (e) {
|
||||
var r;
|
||||
if (s.hasError) return;
|
||||
if (!(r = parseResult(e.target.responseText)) || (r.err || r.error) === true) {
|
||||
error.call(s, file, context, { type: u.ErrorType.ServerType, view: view, message: r ? (r.msg || r.message) : "unknown" });
|
||||
return
|
||||
}
|
||||
if (sliced && index < count - 1) {
|
||||
if (paused === true) { delete file.uploading; }
|
||||
else { setTimeout(function () { sendBlob(index + 1) }, 0) }
|
||||
}
|
||||
///完全上传成功
|
||||
else {
|
||||
success.call(s, file, context, r); file.uploaded = true
|
||||
}
|
||||
}, false);
|
||||
xhr.upload.addEventListener("error", function (e) {
|
||||
if (paused !== true) {
|
||||
var status = xhr.readyState === 4 || xhr.readyState === 3 ? xhr.status : 0;
|
||||
error.call(s, file, context, { type: u.ErrorType.HttpType, code: status, view: view, message: status === 0 ? "unknown" : xhr.statusText })
|
||||
}
|
||||
}, false);
|
||||
if (sliced === true) {
|
||||
s.count = count = Math.ceil(size / blobSize);
|
||||
};
|
||||
//s.proceed()
|
||||
}
|
||||
|
||||
///扩展jQuery方法,为其所有实例添加asyncUploadFiles方法
|
||||
if (u.Support) {
|
||||
jQuery.prototype.asyncUploadFiles = (function (b) {
|
||||
return function (a, e) {
|
||||
if (typeof (b) === "function") { b.apply(this, arguments) }
|
||||
if (a) {
|
||||
if (a.placeholder) delete a.placeholder;
|
||||
if (a.dragable) delete a.dragable;
|
||||
if (a.multiple) delete a.multiple
|
||||
}
|
||||
var up = this.uploader = new u(a, e);
|
||||
jQuery.each(this, function (i, n) {
|
||||
var fs = n.files;
|
||||
if (fs && fs.length) { up.upload(fs) }
|
||||
});
|
||||
}
|
||||
})(jQuery.prototype.asyncUploadFiles)
|
||||
}
|
||||
})();
|
||||
|
||||
586
Uploader/Scripts/Uploader.js
Normal file
586
Uploader/Scripts/Uploader.js
Normal file
@@ -0,0 +1,586 @@
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
|
||||
//公开方法与构造函数
|
||||
//实例化一个上传器,参数settings说明:
|
||||
//object类型:{...}
|
||||
// placeholder:"#btnSelectFiles"//打开文件选择器的占位符,可选的类型:jQuery对象或者字符串类型的jQuery选择器
|
||||
// multiple:true //文件选择器对话框是否支持多选,默认值true
|
||||
// accept:"image/*,text/xml" //接受的文件类型,默认值是空的,即是接受全部类型
|
||||
// dragable:false 可以拖拽文件上传,默认是未开启的
|
||||
// dragContainer:"#container" 拖拽入的容器,可选的类型:jQuery对象或者字符串类型的jQuery选择器
|
||||
// progress:"#box" //文件上传进度列表容器,可选的类型:jQuery对象或者字符串类型的jQuery选择器
|
||||
// blobSize:number //文件切片上传时,单个数据块的大小,单位是字节
|
||||
// sliced:number //是否支持切片上传,可用值:Uploader.Sliced.Auto(0),Uploader.Sliced.Enabled(1),Uploader.Sliced.Disabled(2) 默认值 Uploader.Sliced.Auto
|
||||
// limitSize:number //上传文件大小限制,单位是字节,默认值0 表示没有限制
|
||||
// url:"/fileUpload/handler" //服务端的处理程序,默认值是当前浏览器的地址(location.href)
|
||||
// params:{...} //和文件一起提交到服务端的自定义参数,object类型
|
||||
// parseResult //这个是个函数用来解析服务端返回的结果集 function(serverData) 返回值是object,如果服务端有错误应该返回{err:true,msg:“错误描述”}的对象
|
||||
var u = window.Uploader = function (settings, events) {
|
||||
|
||||
///将帮助信息输出到控制台,如果不要这些帮助信息,可以用 if (!(this instanceof u)){return new u(settings,events)}; 代替下面的if语句
|
||||
if (!(this instanceof u)) {
|
||||
console.log("实例化一个上传器,参数settings说明:"
|
||||
+ "\n 类型是 object:{...}"
|
||||
+ "\n placeholder:\"#btnSelectFiles\"//打开文件选择器的占位符,可选的类型:jQuery对象或者字符串类型的jQuery选择器"
|
||||
+ "\n multiple:true //文件选择器对话框是否支持多选,默认值true"
|
||||
+ "\n accept:\"image/*,text/xml\" //接受的文件类型,默认值是空的,即是接受全部类型"
|
||||
+ "\n dragable:false 可以拖拽文件上传,默认是未开启的"
|
||||
+ "\n dragContainer:\"#container\" 拖拽入的容器,可选的类型:jQuery对象或者字符串类型的jQuery选择器"
|
||||
+ "\n progress:\"#progressBox\" //文件上传进度列表容器,可选的类型:jQuery对象或者字符串类型的jQuery选择器"
|
||||
+ "\n blobSize:number //文件切片上传时,单个数据块的大小,单位是字节"
|
||||
+ "\n sliced:number //是否支持切片上传,可用值:Uploader.Sliced.Auto(0),Uploader.Sliced.Enabled(1),Uploader.Sliced.Disabled(2) 默认值 Uploader.Sliced.Auto"
|
||||
+ "\n limitSize:number //上传文件大小限制,单位是字节,默认值0 表示没有限制"
|
||||
+ "\n url:\"/fileUpload/handler\" //服务端的处理程序,默认值是当前浏览器的地址(location.href)"
|
||||
+ "\n params:{...} //和文件一起提交到服务端的自定义参数,object类型 "
|
||||
+ "\n parseResult: function(serverData) //这个是个函数用来解析服务端返回的结果集,返回值是object,如果服务端有错误应该返回{err:true,msg:\"错误描述\"}的对象");
|
||||
alert("文件上传器实例化的参数说明已经输出到控制台");
|
||||
return;
|
||||
}
|
||||
var s = this
|
||||
, opts = settings || {}
|
||||
, context = { events: {}, files: [] }
|
||||
, sltfsfn = s.upload = function (files) {
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
selecting.apply(s, [files[i], context])
|
||||
}
|
||||
};
|
||||
|
||||
s.version = u.Version;
|
||||
//检查浏览器支持
|
||||
s.support = u.Support;
|
||||
if (!s.support) return false;
|
||||
|
||||
//读取设置
|
||||
s.settings = function (n) {
|
||||
var v = opts[n];
|
||||
return typeof (v) === udfs ? defaultSettings[n] : v;
|
||||
};
|
||||
if (typeof (opts.params) === udfs) { opts.params = {} }
|
||||
if (typeof (opts.types) == "string") { context.types = opts.types.split(';') }
|
||||
|
||||
//事件绑定 可用事件:
|
||||
//selecting 选择文件 function(file,args) args:{ cancel: false,invalidType:false||true }
|
||||
//selected 已经选择了文件 function(file)
|
||||
//upload 开始上传文件 function(file,args) args:{cancel: false}
|
||||
//createProgress 创建进度视图 function(file,args) args:{view:null} args.view:返回已经创建的视图
|
||||
//getResumableInfoHandler 获取续传信息时触发 function(url,params,callback) url:服务端处理程序,params:文件参数 {fileType:string,fileName:string,fileSize:number,blobSize: number,blobCount:number} callback:function(ResumableInfo:{key,index}) 回调函数
|
||||
//progress 更新进度视图 function(file,args) args: {view:当前视图,cancel: false,size :文件大小,loaded:已经上传的大小,percent:0 ~ 100}
|
||||
//complete 文件上传完成 function(file,args) args:{view:当前视图, req: XMLHttpRequest, status:XMLHttpRequest.status}
|
||||
//success 文件上传成功 function(file,args) args:{view:当前视图,responseText: XMLHttpRequest.responseText,cancel: false, req:XMLHttpRequest,responseType: XMLHttpRequest.responseType, responseXML:XMLHttpRequest.responseXML}
|
||||
//error 错误处理 function(file,args) args:{ view: 当前视图,type:Uploader.ErrorType,code:number,message:string }
|
||||
//drop 启动拖拽上传时(dragable=true)在拖拽容器上拖拽时触发的事件
|
||||
//dragover 启动拖拽上传时(dragable=true)在拖拽容器上拖拽时触发的事件
|
||||
//dragleave 启动拖拽上传时(dragable=true)从拖拽容器上拽出时触发的事件
|
||||
|
||||
s.on = function (a) {
|
||||
var args = arguments;
|
||||
if (args.length == 2) { setHandlers(args[0], context.events, args[1]) }
|
||||
else if (a) {
|
||||
for (var n in a) { setHandlers(n, context.events, a[n]) }
|
||||
}
|
||||
//这个if语快是可以移除的,它将事件绑定的说明输出到控制台
|
||||
if (args.length === 0) {
|
||||
console.log("\n selecting 选择文件 function(file,args) args:{ cancel: false,invalidType:false||true }"
|
||||
+ "\n selected 已经选择了文件 function(file)"
|
||||
+ "\n validate 验证文件类型时触发 function(file,args) args:{invalid:true||false,accept:\"image/*,text/xml\"} "
|
||||
+ "\n upload 开始上传文件 function(file,args) args:{cancel: false}"
|
||||
+ "\n createProgress 创建进度视图 function(file,args) args:{view:null} args.view:返回已经创建的视图"
|
||||
+ "\n getResumableInfoHandler 获取续传信息时触发 function(url,params,callback) url:服务端处理程序,params:文件参数 {fileType:string,fileName:string,fileSize:number,blobSize: number,blobCount:number} callback:function(ResumableInfo:{key,index}) 回调函数"
|
||||
+ "\n progress 更新进度视图 function(file,args) args: {view:当前视图,cancel: false,size :文件大小,loaded:已经上传的大小,percent:0 ~ 100}"
|
||||
+ "\n complete 文件上传完成 function(file,args) args:{view:当前视图, req: XMLHttpRequest, status:XMLHttpRequest.status}"
|
||||
+ "\n success 文件上传成功 function(file,args) args:{view:当前视图,responseText: XMLHttpRequest.responseText,cancel: false, req:XMLHttpRequest,responseType: XMLHttpRequest.responseType, responseXML:XMLHttpRequest.responseXML}"
|
||||
+ "\n error 错误处理 function(file,args) args:{ view: 当前视图,type:Uploader.ErrorType,code:number,message:string }"
|
||||
+ "\n drop 启动拖拽上传时(dragable=true)在拖拽容器上拖拽时触发的事件"
|
||||
+ "\n dragover 启动拖拽上传时(dragable=true)在拖拽容器上拖拽时触发的事件"
|
||||
+ "\n dragleave 启动拖拽上传时(dragable=true)从拖拽容器上拽出时触发的事件");
|
||||
alert("事件绑定的说明已经输出到控制台。");
|
||||
}
|
||||
|
||||
};
|
||||
if (events) { s.on(events) }
|
||||
var multiple = s.settings("multiple"), accept = s.settings("accept"), fs;
|
||||
//
|
||||
if (opts.placeholder) {
|
||||
var btn = $(opts.placeholder), fileSelector;
|
||||
fs = btn.find("[type='file']");
|
||||
if (!fs.length) {
|
||||
fs = $(fileSelector = document.createElement("input")).attr("type", "file").css({ display: 'none', opacity: 0 }).appendTo(btn)
|
||||
} else { fileSelector = fs[0] }
|
||||
btn.click(function () { fileSelector.click() });
|
||||
if (multiple) { fs.attr("multiple", "multiple") }
|
||||
if (accept) { fs.attr("accept", accept) }
|
||||
fs.change(function () { sltfsfn(this.files) })
|
||||
}
|
||||
//else {
|
||||
// fs = $("input[type='file']")//.on("change", function () { sltfsfn(this.files) });
|
||||
//}
|
||||
if (s.settings("dragable") || !opts.placeholder) {
|
||||
var drp = s.settings("dragContainer"), defaultDragContainerFlag = false;
|
||||
if (!drp) {
|
||||
defaultDragContainerFlag = true;
|
||||
drp = $(document.createElement("div")).attr("data-default-dragContainer", defaultDragContainerFlag).css({ display: "none", position: "fixed", "z-index": 9999999, top: 0, left: 0, bottom: 0, right: 0, opacity: 0 }).appendTo("body")
|
||||
}
|
||||
else if (!(drp instanceof jQuery)) { drp = $(drp) }
|
||||
if (drp.length) {
|
||||
var dr = drp[0]
|
||||
, dragEnterfn = function (e) {
|
||||
e.preventDefault();
|
||||
if (defaultDragContainerFlag) { clearTimeout(dr.time); dr.time = null; drp.show() }
|
||||
else { drp.addClass("over") }
|
||||
}
|
||||
, dragLeavefn = function (e) {
|
||||
e.preventDefault();
|
||||
if (defaultDragContainerFlag) {
|
||||
if (!dr.time)
|
||||
{ dr.time = setTimeout(function () { drp.hide() }, 10) }
|
||||
}
|
||||
else { drp.removeClass("over") }
|
||||
};
|
||||
|
||||
|
||||
$(document).on({
|
||||
dragleave: dragLeavefn,
|
||||
drop: function (e) {
|
||||
e.preventDefault();
|
||||
drp.removeClass("over")
|
||||
},
|
||||
dragenter: dragEnterfn,
|
||||
dragover: dragEnterfn
|
||||
});
|
||||
dr.addEventListener("dragleave", function (e) {
|
||||
triggerEvents("dragleave", context, function (fn) { fn.call(s, e) })
|
||||
}, false);
|
||||
dr.addEventListener("dragover", function (e) {
|
||||
e = e || window.event;
|
||||
e.stopPropagation();
|
||||
dragEnterfn(e);
|
||||
triggerEvents("dragover", context, function (fn) { fn.call(s, e) });
|
||||
//e.dataTransfer.dropEffect = 'copy' //指定拖放视觉效果
|
||||
}, false);
|
||||
dr.addEventListener("drop", function (e) {
|
||||
e = e || window.event;
|
||||
e.stopPropagation();
|
||||
dragLeavefn(e);
|
||||
//获取文件列表
|
||||
var files = e.dataTransfer ? e.dataTransfer.files : null;
|
||||
e.cancel = false;
|
||||
triggerEvents("drop", context, function (fn) { fn.call(s, e) });
|
||||
if (!e.cancel && files && files.length) { sltfsfn(files) }
|
||||
}, false)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
, udfs = 'undefined';
|
||||
//静态属性和方法
|
||||
u.Version = { major: 1, minor: 0, revision: 0 };
|
||||
u.Version.toString = function () { return this.major + "." + this.minor + "." + this.revision };
|
||||
//检查浏览器支持
|
||||
u.Support = typeof (window.File) !== udfs && typeof (window.FileList) !== udfs && (typeof (window.Blob) === "function" &&
|
||||
(!!window.Blob.prototype.webkitSlice || !!window.Blob.prototype.mozSlice || !!window.Blob.prototype.slice || false));
|
||||
u.Sliced = { Auto: 0, Enabled: 1, Disabled: 2 };
|
||||
u.ErrorType = {
|
||||
//无效的文件类型
|
||||
InvalidType: 0
|
||||
,
|
||||
//超过文件上限
|
||||
UpperLimit: 1
|
||||
,
|
||||
HttpType: 2
|
||||
,
|
||||
ServerType: 3
|
||||
,
|
||||
UserAbort: 4
|
||||
,
|
||||
InvalidOperation: 5
|
||||
};
|
||||
u.SizeToString = function (size, num) {
|
||||
if (typeof (size) !== "number") return size;
|
||||
var unit = "byte", units = ["KB", "MB", "GB", "TB"], l = 1024, fn = function (n) {
|
||||
if (size > l) {
|
||||
size = size / l;
|
||||
unit = n;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (var i = 0; i < units.length; i++)
|
||||
{ if (!fn(units[i])) break }
|
||||
l = Math.pow(10, (typeof (num) !== "number" || num <= 0 ? 3 : num));
|
||||
return (Math.round(size * l) / l) + unit
|
||||
};
|
||||
//默认配置
|
||||
var defaultSettings = {
|
||||
url: location.href
|
||||
, multiple: true
|
||||
///默认是3MB
|
||||
, blobSize: 1024 * 1024 * 3
|
||||
, sliced: u.Sliced.Auto
|
||||
, dragable: false
|
||||
};
|
||||
//私有方法
|
||||
function isValidType(file, context) {
|
||||
var s = this, n = file.name, did = false, args = { invalid: true, accept: s.settings("accept"), types: context.types };
|
||||
triggerEvents("validate", context, function (fn) { fn.call(s, file, args); did = true });
|
||||
if (did) { return !args.invalid }
|
||||
if (!context.types) return true;
|
||||
for (var i = 0; i < context.types.length; i++) {
|
||||
var o = $.trim(context.types[i]);
|
||||
if (!o) continue;
|
||||
if (new RegExp(escape(o) + "$", "i").test(n)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function setHandlers(n, e, fn) {
|
||||
if (typeof (n) !== "string" || typeof (fn) !== "function") return;
|
||||
var h = e[n = n.toUpperCase()];
|
||||
if (!h) { h = e[n] = [] }
|
||||
h.push(fn)
|
||||
|
||||
}
|
||||
function getHandlers(n, e) {
|
||||
return typeof (n) === "string" && e ? e[n.toUpperCase()] : null
|
||||
}
|
||||
function triggerEvents(n, c, b) {
|
||||
var h = getHandlers(n, c.events);
|
||||
if (h) {
|
||||
for (var i = 0; i < h.length; i++) {
|
||||
var fn = h[i];
|
||||
if (typeof (fn) === "function") {
|
||||
try { b(fn) } catch (x) { console.log(x, fn) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//事件
|
||||
function error(file, context, args, msg) {
|
||||
var s = this;
|
||||
s.hasError = true;
|
||||
s.error = args;
|
||||
triggerEvents("error", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) {
|
||||
if (msg = msg || args.message) { s.view.append("<span class='err-info'>" + msg + "</span>") }
|
||||
setTimeout(function () { s.view.remove() }, 5000)
|
||||
}
|
||||
next(context);
|
||||
}
|
||||
function selected(file, context) {
|
||||
var s = this, prog = new Progress(s, file, context);
|
||||
triggerEvents("selected", context, function (fn) { fn.call(s, file) });
|
||||
if (!context.progress) { context.progress = [] }
|
||||
context.progress.push(prog);
|
||||
upload.call(s, file, context);
|
||||
}
|
||||
function selecting(file, context) {
|
||||
var s = this, args = { cancel: false, invalidType: !isValidType.call(s, file, context) };
|
||||
if (args.invalidType) { file.invalidType = true }
|
||||
triggerEvents("selecting", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) {
|
||||
context.files.push(file);
|
||||
selected.apply(s, [file, context])
|
||||
}
|
||||
}
|
||||
|
||||
function upload(file, context) {
|
||||
var s = this, prs = context.progress, args = { cancel: false, maxQueue: s.settings("maxQueue"), queue: context.queue, lastIndex: context.lastIndex || 0 }
|
||||
, prog = context.progress[args.lastIndex];
|
||||
if (typeof (args.queue) !== "number" || args.queue < 0) { args.queue = 0; }
|
||||
if (args.lastIndex < 0) { args.lastIndex = 0; }
|
||||
if (typeof (args.maxQueue) !== "number" || args.maxQueue < 1) { args.maxQueue = 2; }
|
||||
if (args.queue >= args.maxQueue)
|
||||
{ return }
|
||||
context.queue = args.queue + 1;
|
||||
context.lastIndex = args.lastIndex + 1;
|
||||
args.progress = prog;
|
||||
triggerEvents("upload", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) { prog.proceed() }
|
||||
}
|
||||
function createProgress(file, context) {
|
||||
var s = this, ow = s.owner, args = { view: null };
|
||||
triggerEvents("createProgress", context, function (fn) { fn.call(s, file, args) });
|
||||
if (args.view == null) {
|
||||
//创建默认视图
|
||||
var p = ow.settings("progress");
|
||||
if (!p) {
|
||||
p = ow.settings("dragable") && (p = ow.settings("dragContainer")) && (p = p instanceof jQuery ? p : $(p)).length > 0 ? p : $("body")
|
||||
}
|
||||
//else if (p instanceof jQuery) { p = $(p); }
|
||||
var v = args.view = $(document.createElement("div")).appendTo(p);
|
||||
v.append("<h2>" + file.name + "</h2><p>size:" + u.SizeToString(file.size) + "</p><progress></progress>")
|
||||
}
|
||||
return s.view = args.view
|
||||
}
|
||||
function progress(file, context, st) {
|
||||
var s = this, p, args = { cancel: false, size: s.size, sizeString: u.SizeToString(s.size), view: s.view };
|
||||
if (s.sliced === true) {
|
||||
args.loaded = s.loaded + Math.min(st.currentBlobLoaded, s.blobSize)
|
||||
}
|
||||
else {
|
||||
args.loaded = Math.min(st.currentBlobLoaded, s.size)
|
||||
}
|
||||
p = (args.loaded / args.size) * 100;
|
||||
args.percent = p;
|
||||
args.loadedString = u.SizeToString(args.loaded);
|
||||
triggerEvents("progress", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) {
|
||||
s.bar.attr("value", args.percent)
|
||||
}
|
||||
}
|
||||
function success(file, context, result) {
|
||||
var s = this
|
||||
, args = {
|
||||
view: s.view, cancel: false, result: result
|
||||
, req: s.xhr, responseText: s.xhr.responseText, responseType: s.xhr.responseType, responseXML: s.xhr.responseXML
|
||||
};
|
||||
triggerEvents("success", context, function (fn) { fn.call(s, file, args) });
|
||||
if (!args.cancel) { setTimeout(function () { s.view.remove(); }, 5000) }
|
||||
}
|
||||
function complete(file, context) {
|
||||
var s = this, args = { view: s.view, req: s.xhr, status: s.xhr.status };
|
||||
context.queue--;
|
||||
triggerEvents("complete", context, function (fn) { fn.call(s, file, args) });
|
||||
next(context);
|
||||
}
|
||||
function next(context) {
|
||||
var i = context.lastIndex, s;
|
||||
if (i < context.progress.length) {
|
||||
s = context.progress[i];
|
||||
upload.call(s.owner, s.file, context);
|
||||
}
|
||||
}
|
||||
function Progress(owner, file, context) {
|
||||
this.owner = owner;
|
||||
var s = this, xhr, paused, index = 0, count = 1
|
||||
, size = s.size = file.size
|
||||
, blobSize = s.blobSize = owner.settings("blobSize")
|
||||
, sliced = s.sliced = ((sliced = owner.settings("sliced")) === u.Sliced.Enabled || (sliced === u.Sliced.Auto && size > blobSize) ? true : false)
|
||||
, view = (s.view = createProgress.call(s, file, context) || $())
|
||||
, bar = (s.bar = view.find("progress").attr({ "max": 100, "value": 0 }))
|
||||
, limitSize = owner.settings("limitSize")
|
||||
, url = owner.settings("url")
|
||||
, parseResult = owner.settings("parseResult")
|
||||
, appendParams = function (d) {
|
||||
var ps = owner.settings("params");
|
||||
if (sliced) {
|
||||
d.append("blobIndex", index);
|
||||
d.append("blobCount", count);
|
||||
d.append("resumableKey", s.resumableKey);
|
||||
d.append("sliced", sliced);
|
||||
d.append("fileName", file.name);
|
||||
}
|
||||
d.append("types", owner.settings("types") || "");
|
||||
if (owner.settings("accept")) { d.append("accept", owner.settings("accept")) }
|
||||
for (var p in ps) { d.append(p, ps[p]) }
|
||||
}
|
||||
, send = function (f) {
|
||||
|
||||
xhr.open("post", url, true);
|
||||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
var d = new FormData();
|
||||
d.append("file", f);
|
||||
appendParams(d);
|
||||
//console.log("start:"+new Date().toLocaleTimeString());
|
||||
xhr.send(d)
|
||||
}
|
||||
, sendBlob = function (i) {
|
||||
var start = i * blobSize, end = start + blobSize;
|
||||
index = i;
|
||||
s.loaded = start;
|
||||
if (file.slice) {
|
||||
s.blob = file.slice(start, end);
|
||||
}
|
||||
else if (file.webkitSlice) {
|
||||
s.blob = file.webkitSlice(start, end);
|
||||
} else if (file.mozSlice) {
|
||||
s.blob = file.mozSlice(start, end);
|
||||
}
|
||||
|
||||
|
||||
send(s.blob);
|
||||
};
|
||||
|
||||
if (typeof (parseResult) !== "function") { parseResult = function (d) { var r; try { eval("r=" + d) } catch (e) { r = { err: true, msg: "脚本解析错误。" } } return r } }
|
||||
s.file = file;
|
||||
s.loaded = 0;
|
||||
s.blobSize = blobSize = (sliced ? blobSize : size);
|
||||
s.pause = function () {
|
||||
if (!s.hasError && paused !== true) {
|
||||
s.paused = paused = true;
|
||||
if (xhr && file.uploading === true) {
|
||||
xhr.abort();
|
||||
delete file.uploading;
|
||||
}
|
||||
triggerEvents("pause", context, function (fn) { fn.call(s, file, { view: view }); });
|
||||
context.queue--;
|
||||
next(context);
|
||||
}
|
||||
};
|
||||
s.proceed = function () {
|
||||
if (s.hasError || file.uploading === true) { return; }
|
||||
if (file.uploaded === true || file.canceling === true) {
|
||||
error.call(s, file, context
|
||||
, {
|
||||
type: u.ErrorType.InvalidOperation
|
||||
, message: file.canceling ? "the file is canceling" : file.uploaded ? "the file was uploaded" : "invalid operation", view: view
|
||||
});
|
||||
return
|
||||
}
|
||||
if (paused === true) {
|
||||
var a = { view: view, cancel: false };
|
||||
triggerEvents("proceed", context, function (fn) { fn.call(s, file, a); });
|
||||
if (a.cancel) { return; }
|
||||
}
|
||||
file.cancel = s.paused = paused = false; file.uploading = true;
|
||||
if (!sliced) { send(file); return };
|
||||
var gotit = false
|
||||
, args = { sliced: true, fileType: file.type, fileName: file.name, fileSize: size, blobSize: blobSize, blobCount: count }
|
||||
, b = function (info) {
|
||||
if (info && info.key)
|
||||
{ s.resumableKey = info.key }
|
||||
else { throw new Error(info.msg || info.message || "failed to initialize"); }
|
||||
setTimeout(function () { sendBlob(!isNaN(info.index) ? info.index : 0) }, 0)
|
||||
}
|
||||
, errfn = function (a, x, p) {
|
||||
if (!a) { a = { type: u.ErrorType.ServerType, message: "failed to initialize" } }
|
||||
a.view = view;
|
||||
error.call(s, file, context, a); if (x && x.message) console.log(x.message, p)
|
||||
};
|
||||
triggerEvents("getResumableInfoHandler", context, function (fn) { try { fn.call(s, url, args, b) } catch (x) { errfn(null, x, fn) } gotit = true });
|
||||
if (!gotit) {
|
||||
args.method = "getResumableInfo";
|
||||
|
||||
$.ajax({
|
||||
url: url, type: "POST"
|
||||
, data: args
|
||||
, success: function (d) {
|
||||
var resumable = null;
|
||||
try {
|
||||
eval("resumable=" + d);
|
||||
b(resumable)
|
||||
} catch (x) {
|
||||
//获取初始化信息失败
|
||||
errfn(null, x, d);
|
||||
return
|
||||
}
|
||||
}
|
||||
, error: function (req, txt, dd) {
|
||||
//获取初始化信息失败
|
||||
errfn({ type: u.ErrorType.HttpType, code: req.status, message: txt || errorThrown })
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
s.cancel = function () {
|
||||
if (!s.hasError && file.uploaded !== true && file.cancel !== true && file.canceling !== true) {
|
||||
var doit = function (o) {
|
||||
if (o && !(o.err || o.error)) {
|
||||
file.cancel = true; delete file.canceling; bar.attr("value", 0);
|
||||
triggerEvents("cancel", context, function (fn) { fn.call(s, file, { view: view }) })
|
||||
}
|
||||
};
|
||||
s.pause();
|
||||
file.canceling = true;
|
||||
if (sliced) {
|
||||
$.ajax({
|
||||
url: url, type: "POST", data: { method: "deleteResumable", resumableKey: s.resumableKey }
|
||||
, success: function (d) {
|
||||
var r = null;
|
||||
try {
|
||||
eval("r=" + d);
|
||||
doit(r);
|
||||
} catch (x) {
|
||||
errfn(null, x, d);
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
else { doit(true); }
|
||||
}
|
||||
//
|
||||
};
|
||||
if (file.invalidType || (limitSize && !isNaN(limitSize) && file.size > limitSize)) {
|
||||
error.call(s, file, context
|
||||
, { type: file.invalidType ? u.ErrorType.InvalidType : u.ErrorType.UpperLimit, view: view, message: file.invalidType ? "无效文件类型" : "超过上传限制的大小" }
|
||||
);
|
||||
return
|
||||
}
|
||||
xhr = s.xhr = new XMLHttpRequest();
|
||||
if (typeof (owner.settings("timeout")) === "number") { xhr.timeout = owner.settings("timeout") }
|
||||
|
||||
//事件绑定
|
||||
xhr.addEventListener("readystatechange", function (e) {
|
||||
//完成
|
||||
if (xhr.readyState === 4) {
|
||||
if (s.blob) delete s.blob;
|
||||
var status = xhr.status, isSuccess = status >= 200 && status < 300 || status === 304;
|
||||
if (!isSuccess) {
|
||||
if (paused !== true) { error.call(s, file, context, { type: u.ErrorType.HttpType, code: status, view: view, message: xhr.statusText }) }
|
||||
}
|
||||
if (sliced && index >= count - 1 || !sliced) {
|
||||
if (paused === false) {
|
||||
complete.call(s, file, context);
|
||||
s.paused = paused = true;
|
||||
delete file.uploading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, false);
|
||||
xhr.upload.addEventListener("progress", function (e) {
|
||||
progress.call(s, file, context, { currentBlobLoaded: e.loaded, currentBlobSize: e.total, index: index })
|
||||
}, false);
|
||||
xhr.addEventListener("load", function (e) {
|
||||
var r;
|
||||
if (s.hasError) return;
|
||||
if (!(r = parseResult(e.target.responseText)) || (r.err || r.error) === true) {
|
||||
error.call(s, file, context, { type: u.ErrorType.ServerType, view: view, message: r ? (r.msg || r.message) : "unknown" });
|
||||
return
|
||||
}
|
||||
if (sliced && index < count - 1) {
|
||||
if (paused === true) { delete file.uploading; }
|
||||
else { setTimeout(function () { sendBlob(index + 1) }, 0) }
|
||||
}
|
||||
///完全上传成功
|
||||
else {
|
||||
success.call(s, file, context, r); file.uploaded = true
|
||||
}
|
||||
}, false);
|
||||
xhr.upload.addEventListener("error", function (e) {
|
||||
if (paused !== true) {
|
||||
var status = xhr.readyState === 4 || xhr.readyState === 3 ? xhr.status : 0;
|
||||
error.call(s, file, context, { type: u.ErrorType.HttpType, code: status, view: view, message: status === 0 ? "unknown" : xhr.statusText })
|
||||
}
|
||||
}, false);
|
||||
if (sliced === true) {
|
||||
s.count = count = Math.ceil(size / blobSize);
|
||||
};
|
||||
//s.proceed()
|
||||
}
|
||||
|
||||
///扩展jQuery方法,为其所有实例添加asyncUploadFiles方法
|
||||
if (u.Support) {
|
||||
jQuery.prototype.asyncUploadFiles = (function (b) {
|
||||
return function (a, e) {
|
||||
if (typeof (b) === "function") { b.apply(this, arguments) }
|
||||
if (a) {
|
||||
if (a.placeholder) delete a.placeholder;
|
||||
if (a.dragable) delete a.dragable;
|
||||
if (a.multiple) delete a.multiple
|
||||
}
|
||||
var up = this.uploader = new u(a, e);
|
||||
jQuery.each(this, function (i, n) {
|
||||
var fs = n.files;
|
||||
if (fs && fs.length) { up.upload(fs) }
|
||||
});
|
||||
}
|
||||
})(jQuery.prototype.asyncUploadFiles)
|
||||
}
|
||||
})();
|
||||
|
||||
2670
Uploader/Scripts/jquery-2.1.1.intellisense.js
vendored
Normal file
2670
Uploader/Scripts/jquery-2.1.1.intellisense.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9190
Uploader/Scripts/jquery-2.1.1.js
vendored
Normal file
9190
Uploader/Scripts/jquery-2.1.1.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
Uploader/Scripts/jquery-2.1.1.min.js
vendored
Normal file
4
Uploader/Scripts/jquery-2.1.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
Uploader/Scripts/jquery-2.1.1.min.map
Normal file
1
Uploader/Scripts/jquery-2.1.1.min.map
Normal file
File diff suppressed because one or more lines are too long
31
Uploader/Web.Debug.config
Normal file
31
Uploader/Web.Debug.config
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
在下例中,“SetAttributes”转换将更改
|
||||
“connectionString”的值,以仅在“Match”定位器
|
||||
找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<!--
|
||||
|
||||
在下例中,“Replace”转换将替换
|
||||
web.config 文件的整个 <customErrors> 节。
|
||||
请注意,由于
|
||||
在 <system.web> 节点下仅有一个 customErrors 节,因此不需要使用“xdt:Locator”特性。
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
||||
32
Uploader/Web.Release.config
Normal file
32
Uploader/Web.Release.config
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
在下例中,“SetAttributes”转换将更改
|
||||
“connectionString”的值,以仅在“Match”定位器
|
||||
找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation xdt:Transform="RemoveAttributes(debug)" />
|
||||
<!--
|
||||
|
||||
在下例中,“Replace”转换将替换
|
||||
web.config 文件的整个 <customErrors> 节。
|
||||
请注意,由于
|
||||
在 <system.web> 节点下仅有一个 customErrors 节,因此不需要使用“xdt:Locator”特性。
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
||||
20
Uploader/Web.config
Normal file
20
Uploader/Web.config
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
有关如何配置 ASP.NET 应用程序的详细信息,请访问
|
||||
http://go.microsoft.com/fwlink/?LinkId=169433
|
||||
-->
|
||||
<configuration>
|
||||
<!--
|
||||
有关 web.config 更改的说明,请参见 http://go.microsoft.com/fwlink/?LinkId=235367。
|
||||
|
||||
可在 <httpRuntime> 标记上设置以下特性。
|
||||
<system.Web>
|
||||
<httpRuntime targetFramework="4.5" />
|
||||
</system.Web>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.5"/>
|
||||
<httpRuntime/>
|
||||
<pages controlRenderingCompatibilityVersion="4.0"/>
|
||||
</system.web>
|
||||
</configuration>
|
||||
2
Uploader/config/ResumableFilesStore.xml
Normal file
2
Uploader/config/ResumableFilesStore.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resumables />
|
||||
62
Uploader/index.aspx
Normal file
62
Uploader/index.aspx
Normal file
@@ -0,0 +1,62 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.aspx.cs" Inherits="HTML5Uploader.index" %>
|
||||
|
||||
<%@ Register Assembly="Html5Uploader" Namespace="Html5Uploader.Controls" TagPrefix="cc1" %>
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head runat="server">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title></title>
|
||||
<script src="Scripts/jquery-2.1.1.min.js"></script>
|
||||
<%--<script src="Scripts/Uploader.release.min.js"></script>--%>
|
||||
<%--<script src="Scripts/Uploader.min.js"></script>--%>
|
||||
<%--<script src="Scripts/Uploader.js"></script>--%>
|
||||
<script>
|
||||
var prog;
|
||||
function errorhandler(file, args)
|
||||
{
|
||||
alert("args.message=" + args.message + ",invalidType=" + file.invalidType)
|
||||
//if (args.type == Uploader.ErrorType.UserAbort)
|
||||
//{
|
||||
|
||||
//}
|
||||
args.cancel = true;
|
||||
}
|
||||
function createProgress(file, args) {
|
||||
var s = prog = this;
|
||||
prog.file = file;
|
||||
args.view = $(document.createElement("div")).appendTo("body").append("<h2>" + file.name + "</h2><p>size:" + Uploader.SizeToString(file.size) + " <span></span></p> <progress></progress><a href='javascript:' class='pause'>pause</a> <a href='javascript:' class='proceed'>proceed</a> <a href='javascript:' class='cancel'>cancel</a>");
|
||||
args.view.find("a").click(function () {
|
||||
var a = $(this);
|
||||
if (a.hasClass("pause")) {
|
||||
s.pause();
|
||||
}
|
||||
else if (a.hasClass("proceed"))
|
||||
{ s.proceed();}
|
||||
else if (a.hasClass("cancel"))
|
||||
{ s.cancel(); }
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form id="form1" runat="server">
|
||||
|
||||
|
||||
|
||||
<cc1:Html5UploaderClient ID="Html5Uploader1" RegisterScript="true" Url="Handler1.ashx" Dragable="true" BlobSize="500kb"
|
||||
MaxQueue="3" Placeholder="#btnSeletor" runat="server">
|
||||
<ViewTemplate>
|
||||
<a href="javascript:" id="btnSeletor" >select files</a>
|
||||
</ViewTemplate>
|
||||
<ClientEvents>
|
||||
<cc1:ClientEvent EventName="error" Handle="errorhandler" />
|
||||
<cc1:ClientEvent EventName="createProgress" Handle="createProgress" />
|
||||
<%-- <cc1:ClientEvent EventName="validate" Handle="function(sender,arg){/* code ....*/}" />--%>
|
||||
</ClientEvents>
|
||||
</cc1:Html5UploaderClient>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
17
Uploader/index.aspx.cs
Normal file
17
Uploader/index.aspx.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
namespace HTML5Uploader
|
||||
{
|
||||
public partial class index : System.Web.UI.Page
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Uploader/index.aspx.designer.cs
generated
Normal file
33
Uploader/index.aspx.designer.cs
generated
Normal file
@@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <自动生成>
|
||||
// 此代码由工具生成。
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </自动生成>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace HTML5Uploader {
|
||||
|
||||
|
||||
public partial class index {
|
||||
|
||||
/// <summary>
|
||||
/// form1 控件。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 自动生成的字段。
|
||||
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
|
||||
|
||||
/// <summary>
|
||||
/// Html5Uploader1 控件。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 自动生成的字段。
|
||||
/// 若要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
|
||||
/// </remarks>
|
||||
protected global::Html5Uploader.Controls.Html5UploaderClient Html5Uploader1;
|
||||
}
|
||||
}
|
||||
32
Uploader/index.html
Normal file
32
Uploader/index.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>超大文件上传</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=1.0, user-scalable=no" />
|
||||
<script src="Scripts/jquery-2.1.1.min.js"></script>
|
||||
<script src="Scripts/Uploader.js"></script>
|
||||
<!--<script src="Scripts/Uploader.min.js"></script>-->
|
||||
<!--<script src="Scripts/Uploader.release.js"></script>-->
|
||||
<!--<script src="Scripts/Uploader.release.min.js"></script>-->
|
||||
</head>
|
||||
<body>
|
||||
<br />
|
||||
<a href="#" id="btn">select files</a><br />
|
||||
<input id="m" type="file" />
|
||||
<a href="javascript:" id="up">upload</a>
|
||||
|
||||
<script>
|
||||
$("#up").click(function () {
|
||||
$("#m").asyncUploadFiles({ url: "Handler1.ashx" }, { complete: function (f,e) { alert(f.name+"上传已经完成!") }});
|
||||
});
|
||||
var uploader = new Uploader({
|
||||
placeholder: "#btn", url: "Handler1.ashx"//,accept:"image/*",types:".jpg;.gif;.png",limitSize:1024*1024*50
|
||||
, dragable: true//,dragContainer:$("#kk")
|
||||
}, { error: function (file, args) { alert("message:" + args.message + ",type:" + args.type); args.cancel = true; } });
|
||||
Uploader();
|
||||
//var dd = new Uploader({ url: "/dd/dd" });
|
||||
//dd.on();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
4
Uploader/packages.config
Normal file
4
Uploader/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="jQuery" version="2.1.1" targetFramework="net45" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user