ActiveX多线程断点上传插件
该插件利用 "HttpPost" 方式对文件进行切片上传,目前该插件的剩余时间和指定大小切割文件部分还需要继续优化,该插件支持已下功能:
1.文件切片。当选择文件开始上传时会把文件按指定大小进行切割。再post到服务器。
2.多线程。文件上传时可以利用多线程同时对切片上传。
3.断点续传。上传失败时可以紧接之前上传的部分继续上传。
4.显示上传进度。可以动态显示文件的上传进度。
5.显示剩余时间。可以显示文件上传所需要的剩余时间。
6.数据传输加密。上传的信息通过AES加密和MD5校验确保文件的正确性。
7.后台异步上传。选择上传文件后可以关闭上传界面去操作其他事情,利用ActiveX插件进行异步上传。
源码:
/// <summary> /// ActiveX上传插件公开接口 /// </summary> [Guid("587E4BA6-C0F5-4C97-8C29-62A38DAC50A2")] public class ActiveXUpload : UserControl, IObjectSafety { /// <summary> /// 上传控件实例 /// </summary> UploadCore UploadCoreObject = new UploadCore(); #region IObjectSafety 成员 private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"; private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}"; private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}"; private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}"; private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001; private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002; private const int S_OK = 0; private const int E_FAIL = unchecked((int)0x80004005); private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true; private bool _fSafeForInitializing = true; public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions) { int Rslt = E_FAIL; string strGUID = riid.ToString("B"); pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; switch (strGUID) { case _IID_IDispatch: case _IID_IDispatchEx: Rslt = S_OK; pdwEnabledOptions = 0; if (_fSafeForScripting == true) pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; break; case _IID_IPersistStorage: case _IID_IPersistStream: case _IID_IPersistPropertyBag: Rslt = S_OK; pdwEnabledOptions = 0; if (_fSafeForInitializing == true) pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA; break; default: Rslt = E_NOINTERFACE; break; } return Rslt; } public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) { int Rslt = E_FAIL; string strGUID = riid.ToString("B"); switch (strGUID) { case _IID_IDispatch: case _IID_IDispatchEx: if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true)) Rslt = S_OK; break; case _IID_IPersistStorage: case _IID_IPersistStream: case _IID_IPersistPropertyBag: if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true)) Rslt = S_OK; break; default: Rslt = E_NOINTERFACE; break; } return Rslt; } #endregion #region JS调用C#方法 /// <summary> /// 打开悬着上传文件对话框 /// </summary> /// <param name="OperationID">操作id</param> /// <param name="OperationName">操作名称</param> /// <param name="OpenType">文件选择框为单选或多选</param> /// <param name="FileFilter">允许上传文件类型</param> /// <param name="ThreadCount">文件多线程上传时线程数量(1-3)</param> public void OpenFilesWindow(string OperationID, string OperationName, string OpenType, string FileFilter, string SaveFilePath, int ThreadCount) { OpenTypes op = (OpenTypes)Enum.Parse(typeof(OpenTypes), OpenType); OpenFileDialog ofd = new OpenFileDialog(); //ofd.InitialDirectory = @"C:\Users\yaya\Documents\例子\";//对话框的初始目录 ofd.Filter = FileFilter;//要在对话框中显示的文件筛选器 ofd.FilterIndex = 1;//在对话框中选择的文件筛选器的索引,如果选第一项就设为1 ofd.RestoreDirectory = true;//保存对话框是否记忆上次打开的目录 ofd.Title = "请选择文件";//将显示在对话框标题栏中的字符 ofd.FileName = "";//对话框弹出时清空文件名 ofd.Multiselect = op == OpenTypes.Multiple ? true : false;//是否多选 if (ofd.ShowDialog() == DialogResult.OK) { foreach (string item in ofd.FileNames) { string FileID = GetGuid(); long size = new FileInfo(item).Length; UploadCoreObject.Upload(this.Handle, OperationID, OperationName, FileID, item, SaveFilePath, Common.ValidThreadCount(ThreadCount)); CallJS(String.Format("ActiveXJS.UploadObject.AddItem('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}')", OperationID, OperationName, FileID, Path.GetFileName(item), item, Common.GetFileSize(size), 0.00, UploadStatus.Upload.ToString(), String.Empty)); } } } /// <summary> /// 添加上传选项到界面 /// </summary> /// <param name="OperationID">操作id</param> /// <param name="OperationName">操作名称</param> public void LoadUploadList(string OperationID, string OperationName) { OperationQueue operationQueue = UploadCore.OperationQueueList.FirstOrDefault(a => a.OperationID == OperationID); if (operationQueue != null) { foreach (ItemQueue item in operationQueue.ItemQueueList) { CallJS(String.Format("ActiveXJS.UploadObject.AddItem('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}')", OperationID, OperationName, item.ItemID, item.LocalFileName, item.LocalFileFullName, Common.GetFileSize(item.LocalFileSize), UploadCore.GetProgressValue(item).ToString("0.00"), item.Status.ToString(), item.Message)); } } } /// <summary> /// 清除指定选项上传提示信息 /// </summary> /// <param name="OperationID">操作id</param> /// <param name="ItemID">选项id</param> /// <returns></returns> public void ClearMessage(string OperationID, string ItemID) { OperationQueue operationQueue = UploadCore.OperationQueueList.FirstOrDefault(a => a.OperationID == OperationID); if (operationQueue != null) { ItemQueue fileQueue = operationQueue.ItemQueueList.FirstOrDefault(a => a.ItemID == ItemID); if (fileQueue != null) { fileQueue.Message = ""; } } } /// <summary> /// 取消指定选项上传 /// </summary> /// <param name="OperationID">操作id</param> /// <param name="ItemID">选项id</param> /// <returns></returns> public string Cancle(string OperationID, string ItemID) { try { OperationQueue operationQueue = UploadCore.OperationQueueList.FirstOrDefault(a => a.OperationID == OperationID); if (operationQueue != null) { ItemQueue fileQueue = operationQueue.ItemQueueList.FirstOrDefault(a => a.ItemID == ItemID); if (fileQueue != null) { if (fileQueue.Status == UploadStatus.Finish) { fileQueue.Status = UploadStatus.Cancel; UploadCoreObject.Cancle(fileQueue); } else { fileQueue.Status = UploadStatus.Cancel; UploadCoreObject.Cancle(fileQueue); } } } return "ok"; } catch (Exception ex) { return ex.Message; } } /// <summary> /// 清除指定上传操作记录 /// </summary> /// <param name="OperationID">操作id</param> public string ClearHistory(string OperationID) { try { lock (UploadCore.OperationQueueList) { OperationQueue tmp_operationQueue = UploadCore.OperationQueueList.FirstOrDefault(a => a.OperationID == OperationID); if (tmp_operationQueue != null) { UploadCore.OperationQueueList.Remove(tmp_operationQueue); UploadCore.SaveHistoryFile(); } return "ok"; } } catch (Exception ex) { return ex.Message; } } /// <summary> /// 暂停false\继续true指定选项上传 /// </summary> /// <param name="OperationID">操作id</param> /// <param name="ItemID">选项id</param> /// <param name="SCtype">true继续上传fale暂停上传</param> /// <returns></returns> public string SuspendContinue(string OperationID, string ItemID, string SCtype) { try { OperationQueue operationQueue = UploadCore.OperationQueueList.FirstOrDefault(a => a.OperationID == OperationID); if (operationQueue != null) { ItemQueue fileQueue = operationQueue.ItemQueueList.FirstOrDefault(a => a.ItemID == ItemID); if (fileQueue != null) { if (SCtype == "true") { fileQueue.Status = UploadStatus.Upload; UploadCoreObject.Upload(this.Handle, OperationID, operationQueue.OperationName, ItemID, fileQueue.LocalFileFullName, fileQueue.SaveFilePath, fileQueue.ThreadCount); } else { fileQueue.Status = UploadStatus.Suspend; } } } return "ok"; } catch { return "error"; } } /// <summary> /// 设置上传服务器路径 /// </summary> /// <param name="serverPath">上传服务器地址</param> /// <returns></returns> public string SetServerPath(string serverPath) { try { UploadCore.Server = serverPath + "/Upload/UploadHandler.ashx"; return "ok"; } catch (Exception ex) { return ex.Message; } } /// <summary> /// 获取指定操作文件信息 /// </summary> /// <param name="OperationID">操作id</param> /// <returns></returns> public string GetFilesInfo(string OperationID) { OperationFilesResponse ofr = new OperationFilesResponse() { code = 100, msg = "" }; try { OperationQueue tmp_operationQueue = UploadCore.OperationQueueList.FirstOrDefault(a => a.OperationID == OperationID); if (tmp_operationQueue == null) { ofr.code = 500; ofr.msg = "没有上传操作"; goto returnresult; } if (tmp_operationQueue.ItemQueueList.Count < 1) { ofr.code = 501; ofr.msg = "上传列表为空"; goto returnresult; } foreach (ItemQueue itemQueue in tmp_operationQueue.ItemQueueList) { if (itemQueue.Status != UploadStatus.Finish) { ofr.code = 502; ofr.msg = "上传未完成"; goto returnresult; } } ofr.OperationID = tmp_operationQueue.OperationID; ofr.OperationName = tmp_operationQueue.OperationName; ofr.OperationDate = tmp_operationQueue.OperationDate; ofr.ItemFilesResponseList = new List<ItemFilesResponse>(); foreach (ItemQueue itemQueue in tmp_operationQueue.ItemQueueList) { ItemFilesResponse ifr = new ItemFilesResponse(); ifr.ItemID = itemQueue.ItemID; ifr.SaveFilePath = itemQueue.SaveFilePath; ifr.SaveFileName = String.Format("{0}_{1}", itemQueue.ItemID, itemQueue.LocalFileName); ifr.FileFullName = itemQueue.LocalFileFullName; ofr.ItemFilesResponseList.Add(ifr); } returnresult: return JsonConvert.SerializeObject(ofr); } catch (Exception ex) { ofr.code = 503; ofr.msg = ex.Message; return JsonConvert.SerializeObject(ofr); } } /// <summary> /// 生成唯一编号 /// </summary> /// <returns></returns> public string GetGuid() { return Guid.NewGuid().ToString(); } #endregion #region C#调用JS函数 private Type typeIOleObject = null; private IOleClientSite oleClientSite = null; private IOleContainer pObj = null; /// <summary> /// 接受上传线程发来的信息 /// </summary> /// <param name="m"></param> protected override void WndProc(ref Message m) { switch (m.Msg) { case UploadCore.Custom_UpdateProgress://更新上传进度 { UploadCore.UpdateProgressStruct ups = (UploadCore.UpdateProgressStruct)Marshal.PtrToStructure(m.LParam, typeof(UploadCore.UpdateProgressStruct)); this.CallJS(String.Format("ActiveXJS.UploadObject.UpdateItemProgress('{0}','{1}','{2}')", ups.OperationID, ups.ItemID, ups.ProgressValue.ToString("0.00"))); return; } case UploadCore.Custom_UpdateRemainTime://更新剩余总时间 { UploadCore.UpdateRemainTimeStruct urts = (UploadCore.UpdateRemainTimeStruct)Marshal.PtrToStructure(m.LParam, typeof(UploadCore.UpdateRemainTimeStruct)); this.CallJS(String.Format("ActiveXJS.UploadObject.UpdateItemRemainTime('{0}','{1}','{2}')", urts.OperationID, urts.ItemID, urts.RemainTime)); return; } case UploadCore.Custom_UpdateMessage://更新上传信息 { UploadCore.UpdateMessageStruct ums = (UploadCore.UpdateMessageStruct)Marshal.PtrToStructure(m.LParam, typeof(UploadCore.UpdateMessageStruct)); this.CallJS(String.Format("ActiveXJS.UploadObject.UpdateItemMessage('{0}','{1}','{2}')", ums.OperationID, ums.ItemID, ums.Message)); return; } case UploadCore.Custom_UpdateFinish://更新上传状态为完成 { UploadCore.UpdateMessageStruct ums = (UploadCore.UpdateMessageStruct)Marshal.PtrToStructure(m.LParam, typeof(UploadCore.UpdateMessageStruct)); this.CallJS(String.Format("ActiveXJS.UploadObject.UpdateItemFinish('{0}','{1}')", ums.OperationID, ums.ItemID)); return; } default: { base.WndProc(ref m); return; } } } /// <summary> /// 调用JS函数 /// </summary> /// <param name="JscriptContent">js函数</param> protected void CallJS(string JscriptContent) { if (typeIOleObject == null) { typeIOleObject = this.GetType().GetInterface("IOleObject", true); object tmpOldClientSite = typeIOleObject.InvokeMember("GetClientSite", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public, null, this, null); oleClientSite = tmpOldClientSite as IOleClientSite; oleClientSite.GetContainer(out pObj); } IHTMLDocument2 pDoc2 = (IHTMLDocument2)pObj; try { pDoc2.parentWindow.execScript(JscriptContent, "jscript"); } catch (Exception ex) { MessageBox.Show(ex.Message + ex.StackTrace); } } #endregion }
源码下载地址:ActiveX多线程断点上传插件.zip