WCF大文件傳輸【轉】

http://www.cnblogs.com/happygx/archive/2013/10/29/3393973.htmlhtml

 

  WCF傳輸文件的時候能夠設置每次文件的傳輸大小,若是是小文件的時候,能夠很方便的將文件傳遞到服務端,可是若是文件比較大的話,就不可取了數據庫

遇到大文件的話能夠採起分段傳輸的方式進行文件傳輸服務器

思路:多線程

一、客戶端循環傳遞併發

二、將文件分割成指定大小的字節塊app

三、每次傳輸一小塊後,客戶端將當前文件的讀取指針移動到指定位置函數

四、服務端每次依照傳遞過來的字節文件追加post

問題:假設文件有好幾個G大小,按照上述方式進行文件傳輸,當文件傳遞到99%的時候忽然因爲客觀緣由而形成文件傳輸失敗,直接會形成服務器已經上傳的文件不可用,必須從新上傳this

解決方案:url

能夠採起斷點續傳的模式

一、當服務器第一次傳輸文件的時候,能夠先經過服務檢查服務器上是否已經存在當前文件,若是存在則返回服務器上文件的最大指針位置,若是不存在則默認爲0

二、判斷服務器指針最大位置是否大於等於當前文件指針位置;若是大於等於,則文件已經存在

  a)大於等於:因爲每次上傳的文件字節數是固定的,假設傳遞到最後一塊,本地文件小於要求的傳遞數量,服務端仍是按照規定大小的字節數進行寫文件

二、客戶端拿到服務器上返回的文件指針位置後,循環發送文件開始,將讀取文件指針直接移動到服務器返回的文件指針位置

 

文件傳輸案例:

一、能夠斷點續傳

二、同時傳輸多臺服務器

三、顯示計算當前文件的上傳速度

四、傳遞完成後文件自動解壓

一:客戶端服務鏈接

複製代碼
 //同時存在多臺服務器
                                    string[] SynServiceAddress = ConfigurationSettings.AppSettings["IpAddress"].ToString().Split('|');
                                    SynFilesContract.Course.SynCustomServerFileInfo cusSelectPath = new SynFilesContract.Course.SynCustomServerFileInfo(new FileInfo(ServicePath));
                                    ChannelFactory<SynFilesContract.SynIFileServicesInterface> duplexChannelFactory = null;
                                    string ServiceFileName = "\\" + fileName;
                                    for (int i = 0; i < SynServiceAddress.Length; i++)
                                    {
                                        string ServiceIP = SynServiceAddress[i];
                                        if (ServiceIP != "")
                                        {
                                            ServiceIP = ServiceIP + "/Design_Time_Addresses/SynFilesContract/Service1/";
                                            EndpointAddress address = new EndpointAddress(ServiceIP);

                                            //設置傳輸類型協議
                                            WSHttpBinding binding = new WSHttpBinding();
                                            //設置協議屬性
                                            binding.Security.Mode = System.ServiceModel.SecurityMode.None;
                                            binding.MaxReceivedMessageSize = 2147483647;
                                            binding.ReaderQuotas = new XmlDictionaryReaderQuotas() { MaxStringContentLength = 2147483647 };
                                            binding.SendTimeout = TimeSpan.Parse("00:10:00");
                                            binding.CloseTimeout = TimeSpan.Parse("12:00:00");
                                            binding.ReceiveTimeout = TimeSpan.Parse("23:10:00");
                                            binding.OpenTimeout = TimeSpan.Parse("00:01:00");
                                            binding.ReliableSession.Enabled = false;
                                            binding.ReliableSession.InactivityTimeout = TimeSpan.Parse("23:10:00");
                                            binding.MessageEncoding = WSMessageEncoding.Mtom;
                                            duplexChannelFactory = new ChannelFactory<SynFilesContract.SynIFileServicesInterface>(binding, address);

                                            binding.MessageEncoding = WSMessageEncoding.Mtom;
                                            ServiceThrottlingBehavior Behavior = new ServiceThrottlingBehavior();
                                            //限流與PerCall     MaxConcurrentCalls與MaxConcurrentInstances控制每一個服務的吞吐量
                                            int CallsNum = 1000;
                                            int InstancesNum = 1000;
                                            int SessionNum = 1000;
                                            try { CallsNum = int.Parse(ConfigurationManager.AppSettings["MaxConcurrentCalls"].ToString()); }
                                            catch { }
                                            try { InstancesNum = int.Parse(ConfigurationManager.AppSettings["MaxConcurrentInstances"].ToString()); }
                                            catch { }
                                            try { SessionNum = int.Parse(ConfigurationManager.AppSettings["MaxConcurrentSessions"].ToString()); }
                                            catch { }
                                            //最大併發調用  
                                            Behavior.MaxConcurrentCalls = CallsNum;
                                            //最大併發實例
                                            Behavior.MaxConcurrentInstances = InstancesNum;
                                            //最大併發會話
                                            Behavior.MaxConcurrentSessions = SessionNum;

                                            FileUpload fileUpload = new FileUpload(cusSelectPath, duplexChannelFactory, ServiceFileName, UserId, CourseType, ServiceIP, CoursePathNow);
                                            //針對傳遞不一樣的服務器啓用多線程傳輸
                                            Thread thread = new Thread(fileUpload.Start);
                                            thread.Start();
                                            //添加文件服務器上傳路徑
                                            /// <summary>
                                            /// 文件服務器同步記錄
                                            /// </summary>
                                            /// <param name="fileName">文件名稱</param>
                                            /// <param name="ServicePath">文件在服務器的IP地址</param>
                                            /// <param name="FileType">處理文件類型,1  文件上傳完成、刪除Xml文件記錄,2,文件正在上傳</param>
                                            /// <param name="inThread">發送給其餘文件服務器啓用的線程</param>
                                            /// <param name="userId">用戶ID(解壓壓縮文件同步時用到)</param>
                                            /// <param name="courseType">上傳的文件類型</param>
                                            /// <param name="CoursePathNow">上傳到文件服務器的地址</param>
                                            fileUpload.AddFilePercent(fileName, cusSelectPath.FullName, CourseType, ServiceIP, thread, CoursePathNow);
複製代碼

構造函數:

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Xml.Linq;
using ICSharpCode.SharpZipLib.Zip;

namespace FileServicesBLLContract.Common
{

    public delegate void OnDownPosChanage(int pos, long speed);
    public delegate void OnDownOver();
    public enum MakeFileType
    {
        Down,
        Upload
    }
    public class FileUpload
    {
        /// <summary>
        /// 線程的集合
        /// </summary>
        public List<Thread> list = new List<Thread>();
        /// <summary>
        /// 計數器
        /// </summary>
        public static List<int> listCertificateContract = listCertificate();
        /// <summary>
        /// 初始化計數器
        /// 一、二、三、4分別表明不一樣的處理服務器
        /// </summary>
        /// <returns></returns>
        private static List<int> listCertificate()
        {
            List<int> listCertificate = new List<int>();
            listCertificate.Add(1);
            listCertificate.Add(2);
            listCertificate.Add(3);
            listCertificate.Add(4);
            return listCertificate;
        }

        public event OnDownPosChanage OnChange = null;
        public event OnDownOver OnDownOver = null;
        public int DowPrcet = 0;
        public struct DownInfo
        {
            public MakeFileType MakeFileType;
            public SynFilesContract.SynIFileServicesInterface Contract;
            public SynFilesContract.Course.SynCustomServerFileInfo CurrentFileInfo;
            public long offset;
        }
        public DownInfo CurrentDownInfo = new DownInfo();
        //文件名稱
        public string LocalFileName = string.Empty;
        //文件全路徑名
        public string LocalFileFullName = string.Empty;
        //一秒前文件上傳速度大小
        public long UpdateFileSpeedFirst = 0;
        //一秒後文件上傳大小
        public long UpdateFileSpeedEnd = 0;
        //當前時間
        public DateTime dt = DateTime.Now;
        //一秒後時間
        public string EndUploadFileSpeed = "";

        //文件服務器文件所在的地址(續傳時須要讀取改地址)
        public string ServicePath = "";

        //上傳到的具體地址
        public string CoursePathNow = "";

        //上傳文件的大小
        public long FileLength = 0;
        public Thread th = null;
        /// <summary>
        /// 用戶ID
        /// </summary>
        string UserId = "";
        /// <summary>
        /// 上傳的類型
        /// </summary>
        string CourseType = "";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="CurretFileInfo"></param>
        /// <param name="Channel"></param>
        /// <param name="LocalFileName"></param>
        /// <param name="userId"></param>
        /// <param name="courseType"></param>
        /// <param name="servicePath">文件服務器文件所在的地址,續傳有值,上傳時傳入""</param>
        public FileUpload(SynFilesContract.Course.SynCustomServerFileInfo CurretFileInfo, ChannelFactory<SynFilesContract.SynIFileServicesInterface> Channel, string LocalFileName, string userId, string courseType, string servicePath, string coursePathNow)
        {
            CoursePathNow = coursePathNow;
            ServicePath = servicePath;
            UserId = userId;
            CourseType = courseType;
            SynFilesContract.SynIFileServicesInterface Contract = Channel.CreateChannel();
            CurrentDownInfo.CurrentFileInfo = CurretFileInfo;
            CurrentDownInfo.Contract = Contract;
            this.LocalFileName = LocalFileName;
            this.LocalFileFullName = CurretFileInfo.FullName;
        }

        public void Start()
        {
            string UrlAddress = ConfigurationManager.AppSettings["UrlAddress"].ToString();
            //for (int i = 0; i < UrlAddress.Split('|').Length; i++)
            //{
            Thread thread = new Thread(UploadFile);
            thread.Start();
            //}
        }
        /// <summary>
        ///  上傳方法
        /// </summary>
        public void UploadFile()
        {
            int UploadF = 0;
            int UploadXml = 0;
            string path = "";
            string UrlAddress = ConfigurationManager.AppSettings["UrlAddress"].ToString();
            path = UrlAddress + CoursePathNow + "\\";
            //表示須要續傳
            //if (ServicePath != "")
            //{
            //    path = ServicePath;
            //}
            //else
            //{
            //    int Url = listCertificateContract[0];
            //    listCertificateContract.Add(listCertificateContract[0]);
            //    listCertificateContract.RemoveAt(0);
            //    if (Url == 1)
            //    {
            //        path = UrlAddress.Split('|')[0].ToString();
            //    }
            //    else if (Url == 2)
            //    {
            //        path = UrlAddress.Split('|')[1].ToString();
            //    }
            //    else if (Url == 3)
            //    {
            //        path = UrlAddress.Split('|')[2].ToString();
            //    }
            //    else
            //    {
            //        path = UrlAddress.Split('|')[3].ToString();
            //    }
            //}
            //lock (this)
            //{
            EndUploadFileSpeed = dt.AddSeconds(2).ToLongTimeString();
            FileStream fs = new FileStream(this.CurrentDownInfo.CurrentFileInfo.FullName, FileMode.Open, FileAccess.Read);
            byte[] buffer = new byte[102400];
            bool result = true;
            NewFile(path);
            //初始化查詢服務器上面當前文件的字節位置大小
            long dataInfo = CurrentDownInfo.Contract.GetFilesLength(this.LocalFileName, path);
            AutoResetEvent ar = new AutoResetEvent(false);
            //定位當前文件的續傳位置
            fs.Position = dataInfo;
            //用全局變量獲取文件的大小,不用每次都讀取
            //FileLength = fs.Read(buffer, 0, buffer.Length);
            try
            {
                while ((dataInfo = fs.Read(buffer, 0, buffer.Length)) > 0)
                {

                    ar.Reset();
                    //開始傳輸
                    CurrentDownInfo.Contract.BeginUploadFile(this.LocalFileName, fs.Position - dataInfo, buffer, this.LocalFileFullName, path, fs.Length,
                          new AsyncCallback(delegate(IAsyncResult ra)
                          {
                              try
                              {
                                  result = CurrentDownInfo.Contract.EndUploadFile(ra);
                              }
                              catch 
                              {
                                  result = false;
                              }
                              ar.Set();
                          }), null);
                    ar.WaitOne();
                    if (!result)
                    {
                        if (UploadF >= 3)
                        {
                            break;
                        }
                        else
                        {
                            //若是傳輸完成,則更新文件的傳輸記錄
                            UploadFile();
                        }
                        UploadF++;
                    }
                    if (dt.ToLongTimeString() == EndUploadFileSpeed)
                    {
                        EndUploadFileSpeed = dt.AddSeconds(2).ToLongTimeString();
                        dt = DateTime.Now;
                        //後秒前文件上傳速度大小  即當前傳輸文件的速度
                        UpdateFileSpeedEnd = ((UpdateFileSpeedFirst - (fs.Length - fs.Position)) / 1024) / 2;
                        //前秒前文件上傳速度大小
                        UpdateFileSpeedFirst = 0;
                    }
                    else
                    {
                        dt = DateTime.Now;
                        if (UpdateFileSpeedFirst == 0)
                        {
                            UpdateFileSpeedFirst = fs.Length - fs.Position;
                        }
                    }
                    CurrentDownInfo.offset = fs.Position;
                    int pos = Convert.ToInt32(CurrentDownInfo.offset * 100 / fs.Length);
                    if (DowPrcet != pos)
                    {
                        DowPrcet = pos;
                        if (OnChange != null)
                        {
                            OnChange(DowPrcet, UpdateFileSpeedEnd);
                        }
                    }
                    if (fs.Position >= fs.Length)
                    {

                        if (UploadXml >= 3)
                        {
                            //文件已經上傳完成
                            //RemoveFilePercent(this.LocalFileName, this.CurrentDownInfo.CurrentFileInfo.FullName, "1", path);
                            break;
                        }
                        else
                        {
                            //fs.Close();
                            //fs.Dispose();
                            Thread.Sleep(1000);
                            RemoveFilePercent(this.LocalFileName, this.CurrentDownInfo.CurrentFileInfo.FullName, "1", ServicePath, fs, CoursePathNow);
                        }
                        UploadXml++;
                    }
                }
            }
            catch

            { }

            fs.Close();
            fs.Dispose();
            if (result)
            {
                if (OnDownOver != null)
                {
                    OnDownOver();
                }
            }
            //}
            //sw.Stop();
            //MessageBox.Show(sw.ElapsedMilliseconds.ToString());
        }
        /// <summary>
        /// 文件服務器同步記錄
        /// </summary>
        /// <param name="fileName">文件名稱</param>
        /// <param name="ServicePath">文件在服務器的IP地址</param>
        /// <param name="FileType">處理文件類型,1  文件上傳完成、刪除Xml文件記錄,2,文件正在上傳</param>
        /// <param name="inThread">發送給其餘文件服務器啓用的線程</param>
        /// <param name="userId">用戶ID(解壓壓縮文件同步時用到)</param>
        /// <param name="courseType">上傳的文件類型</param>
        /// <param name="CoursePathNow">上傳到文件服務器的地址</param>
        public void AddFilePercent(string fileName, string FilePath, string FileType, string ServicePath, Thread inThread, string CoursePathNow)
        {

            if (th == null)
            {
                th = inThread;
            }
            lock (this)
            {
                fileName = fileName.Replace("/", "").Replace("\\", "");

                //添加XML
                string userXmlPath = "SynFileXml/SysFile.xml";
                if (!Directory.Exists("SynFileXml"))
                {
                    Directory.CreateDirectory("SynFileXml");
                }

                if (FileType == "2")
                {
                    XDocument doc = null;
                    //string UrlAddress = ConfigurationManager.AppSettings["IpAddress"].ToString();
                    if (File.Exists(userXmlPath))
                    {
                        doc = XDocument.Load(userXmlPath);

                        //爲Xml之追加節點,
                        doc.Element("Data").Add(
                            new XElement("Files",
                                new XElement("FileName", fileName),
                                 new XElement("UserId", UserId),
                                new XElement("CourseType", CourseType),
                                new XElement("FilePath", FilePath),
                                new XElement("CoursePathNow", CoursePathNow),
                                new XElement("ServicePath", ServicePath)));
                    }
                    else
                    {

                        //已上傳
                        doc = new XDocument(new XElement("Data",
                      new XElement("Files",
                          new XElement("FileName", fileName),
                           new XElement("UserId", UserId),
                           new XElement("CourseType", CourseType),
                          new XElement("FilePath", FilePath),
                          new XElement("CoursePathNow", CoursePathNow),
                          new XElement("ServicePath", ServicePath))));

                    }
                    doc.Save(userXmlPath);
                }
                else
                {
                    //若是文件存在
                    //以前已經上傳過,應該往現有文件裏面添加新的節點數據
                    if (File.Exists(userXmlPath))
                    {
                        XDocument doc = XDocument.Load(userXmlPath);
                        var s1 = from s in doc.Element("Data").Elements("Files") where s.Element("FileName").Value == fileName && s.Element("ServicePath").Value == ServicePath select s;
                        //若是當前文件上傳信息存在
                        if (s1.Count() > 0)
                        {
                            if (FileType == "1")
                            {
                                //若是文件已經上傳完成
                                s1.Remove();
                                doc.Save(userXmlPath);
                            }

                        }
                        else
                        {
                            //若是當前文件上傳信息不存在,則是新上傳的文件,須要添加新的文件節點信息
                            //爲Xml之追加節點,
                            doc.Element("Data").Add(
                                new XElement("Files",
                                    new XElement("FileName", fileName),
                                    new XElement("UserId", UserId),
                                    new XElement("CourseType", CourseType),
                                    new XElement("FilePath", FilePath),
                                    new XElement("CoursePathNow", CoursePathNow),
                                    new XElement("ServicePath", ServicePath)));
                            doc.Save(userXmlPath);
                        }
                    }
                    else
                    {
                        //已上傳
                        XDocument doc = new XDocument(new XElement("Data",
                       new XElement("Files",
                           new XElement("FileName", fileName),
                           new XElement("UserId", UserId),
                           new XElement("CourseType", CourseType),
                           new XElement("FilePath", FilePath),
                           new XElement("CoursePathNow", CoursePathNow),
                           new XElement("ServicePath", ServicePath))));
                        doc.Save(userXmlPath);

                    }
                }
            }
        }



        /// <summary>
        /// 文件服務器同步記錄
        /// </summary>
        /// <param name="fileName">文件名稱</param>
        /// <param name="ServicePath">文件服務器的ip地址</param>
        /// <param name="FileType">處理文件類型,1  文件上傳完成、刪除Xml文件記錄,2,文件正在上傳</param>
        public void RemoveFilePercent(string fileName, string FilePath, string FileType, string ServicePath, FileStream fs, string CoursePathNow)
        {

            lock (this)
            {
                fileName = fileName.Replace("/", "").Replace("\\", "");

                //添加XML
                string userXmlPath = "SynFileXml/SysFile.xml";
                if (!Directory.Exists("SynFileXml"))
                {
                    Directory.CreateDirectory("SynFileXml");
                }


                //若是文件存在
                //以前已經上傳過,應該往現有文件裏面添加新的節點數據
                if (File.Exists(userXmlPath))
                {
                    XDocument doc = XDocument.Load(userXmlPath);
                    var s1 = from s in doc.Element("Data").Elements("Files") where s.Element("FileName").Value == fileName && s.Element("ServicePath").Value == ServicePath && s.Element("CoursePathNow").Value == CoursePathNow select s;
                    //若是當前文件上傳信息存在
                    if (s1.Count() > 0)
                    {
                        if (FileType == "1")
                        {

                            //若是文件已經上傳完成
                            s1.Remove();
                            doc.Save(userXmlPath);
                            //上傳完成
                            var s2 = from s in doc.Element("Data").Elements("Files") where s.Element("FileName").Value == fileName select s;
                            if (s2.Count() == 0 || s2 == null)
                            {
                                Thread.Sleep(1000);
                                try
                                {
                                    fs.Close();
                                    fs.Dispose();
                                    if (th != null)
                                    {
                                        th.Abort();
                                        th.Join();
                                    }
                                    //解壓 2012-09-25 ning 
                                    if (fileName.Split('.')[1].ToString() == "rar" || fileName.Split('.')[1].ToString() == "zip")
                                    {
                                        UnZip.UnZipFile(FilePath, FilePath.Substring(0, FilePath.LastIndexOf("\\") + 1) + fileName.Split('.')[0].ToString() + "/");
                                    }
                                    Thread.Sleep(1000);
                                    //刪除文件上傳的壓縮文件
                                    File.Delete(FilePath);
                                    //調用同步文件寫入數據庫的方法
                                    Thread.Sleep(3000);
                                    RescSyn.RescSyn.SynSource(UserId, CourseType);

                                }
                                catch
                                {

                                }
                            }
                        }

                    }
                    else
                    {
                        //若是當前文件上傳信息不存在,則是新上傳的文件,須要添加新的文件節點信息
                        //爲Xml之追加節點,
                        doc.Element("Data").Add(
                            new XElement("Files",
                                new XElement("FileName", fileName),
                                new XElement("FilePath", FilePath),
                                new XElement("ServicePath", ServicePath)));
                        doc.Save(userXmlPath);
                    }
                }
                else
                {
                    //已上傳
                    XDocument doc = new XDocument(new XElement("Data",
                   new XElement("Files",
                       new XElement("FileName", fileName),
                       new XElement("FilePath", FilePath),
                       new XElement("ServicePath", ServicePath))));
                    doc.Save(userXmlPath);

                }

            }
        }
        #region 考試管理服務1


        //傳入文件地址,若是不存在則建立
        /// <summary>
        /// 文件地址
        /// </summary>
        /// <param name="filePath"></param>
        public void NewFile(string filePath)
        {
            string[] arrS = filePath.Replace("/", "\\").Split('\\');
            string path = arrS[0].ToString();
            for (int i = 1; i < arrS.Length; i++)
            {
                if (arrS[i].ToString() != "")
                {
                    path += "\\" + arrS[i].ToString();
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                }
            }
        }

    }
        #endregion



   
}
複製代碼

三:解壓公共方法:

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FileServicesBLLContract.Common
{
    public class UnZip
    {
        /// <summary>
        /// 解壓文件
        /// </summary>
        /// <param name="SrcFile">壓縮包路徑</param>
        /// <param name="DstFile">要解壓的路徑</param>
        public static void UnZipFile(string SrcFile, string DstFile)
        {
            string[] FileProperties = new string[2];
            FileProperties[0] = SrcFile;//待解壓的文件  
            FileProperties[1] = DstFile;//解壓後放置的目標目錄  
            UnZipClass UnZc = new UnZipClass();
            UnZc.UnZip(FileProperties);

        }
    }
}
複製代碼
複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
using System.IO;

namespace FileServicesBLLContract.Common
{
   public class UnZipClass
    {
       public void UnZip(string[] args)
       {
           ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]));

           ZipEntry theEntry;
           while ((theEntry = s.GetNextEntry()) != null)
           {

               string directoryName = Path.GetDirectoryName(args[1]);
               string fileName = Path.GetFileName(theEntry.Name);

               //生成解壓目錄  
               //Directory.CreateDirectory(directoryName);

               if (!Directory.Exists(directoryName))
               {
                   Directory.CreateDirectory(directoryName);
               }

               if (fileName != String.Empty)
               {
                   string filePath = (args[1] + theEntry.Name).Replace(fileName, "");
                   if (!Directory.Exists(filePath))
                   {
                       Directory.CreateDirectory(filePath);
                   }
                   //解壓文件到指定的目錄  
                   FileStream streamWriter = File.Create((args[1] + theEntry.Name).Replace("'", ""));

                   int size = 2048;
                   byte[] data = new byte[2048];
                   while (true)
                   {
                       size = s.Read(data, 0, data.Length);
                       if (size > 0)
                       {
                           streamWriter.Write(data, 0, size);
                       }
                       else
                       {
                           break;
                       }
                   }

                   streamWriter.Close();
               }
           }
           s.Close();
       }
    }
}
複製代碼

四:服務端:

服務接口

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.IO;
using SynFilesContract.Course;
using ELearning.Model.Course;

namespace SynFilesContract
{
    // 注意: 若是更改此處的接口名稱 "IContract",也必須更新 App.config 中對 "IContract" 的引用。
    [ServiceContract]
    public interface SynIFileServicesInterface
    {
        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="file">文件對象</param>
        /// <param name="type">上傳文件類型 0、照片;一、SCROM文件;二、三分屏文件</param>\
        /// <param name="UrlName">課件編號</param>
        /// 
        /// <param name="UrlName">課程編號</param>
        /// <returns></returns>
        [OperationContract]
        UploadFileInfo UplodaFile(UploadFileInfo file, string Type, string UrlName, string Path);




        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="strPath">文件名</param>
        /// <param name="offSet">當前指針</param>
        /// <param name="intoBuffer">每次上傳字節大小</param>
        /// <param name="UploadType">上傳文件類型一、SCROM課程   二、ThreadSreen課程</param>
        /// <param name="UserId">用戶Id</param>
        /// <param name="PathNow">當前文件上傳路徑</param>
        /// <param name="FullName">客戶端文件上傳路徑</param>
        /// <param name="FileLength">客戶端文件原始字節長度</param>
        /// <returns></returns>
        [OperationContract]
        bool UploadFile(string FileName, long offSet, byte[] intoBuffer,string FullName, string Path,long FileLength);
        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginUploadFile(string strPath, long offSet, byte[] intoBuffer,  string FullName, string Path,long FileLength, AsyncCallback ra, object state);
        bool EndUploadFile(IAsyncResult ra);

        /// <summary>
        /// 獲取文件當前上傳的長度
        /// </summary>
        /// <param name="FileName">文件名</param>
        /// <param name="UploadType">上傳文件類型一、SCROM課程   二、ThreadSreen課程</param>
        /// <param name="UserId">用戶Id</param>
        /// <param name="PathNow">當前文件上傳路徑</param>
        /// <returns>長度</returns>
        [OperationContract]
        long GetFilesLength(string FileName,string paths);
    }
   
}
複製代碼

實現:

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;
using System.Threading;
using ELearning.Model.Course;
using ICSharpCode.SharpZipLib.Zip;
using System.ServiceModel;
using ServicesHelper.Base;

namespace SynFilesContract
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class SynFileServiceContract : SynIFileServicesInterface
    {
        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="file">文件對象</param>
        /// <param name="type">上傳文件類型 0、照片;一、SCROM文件;二、三分屏文件</param>\
        /// <param name="UrlName">課件編號</param>
        /// <param name="UrlName">課程編號</param>
        /// <returns></returns>

        public UploadFileInfo UplodaFile(UploadFileInfo file, string Type, string UrlName, string Path)
        {
            try
            {
                return Course.UploadFile.UplodaFile(file, Type, UrlName, Path);
            }
            catch (Exception ex)
            {

                WriteLog.WriteErrorLog(ex, "UplodaFile");
                return null;
       
            }
        }


        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="strPath">文件名</param>
        /// <param name="offSet">當前指針</param>
        /// <param name="intoBuffer">每次上傳字節大小</param>
        /// <param name="UploadType">上傳文件類型一、SCROM課程   二、ThreadSreen課程</param>
        /// <param name="UserId">用戶Id</param>
        /// <param name="PathNow">當前文件上傳路徑</param>
        /// <returns></returns>
        public bool UploadFile(string FileName, long offSet, byte[] intoBuffer, string FullName, string Paths, long FileLength)
        {
            lock (this)
            {
                //標準話文件名
                FileName = FileName.Replace("/", "").Replace("\\", "");
                NewFile(Paths);
                string Path = Paths + FileName;
                if (offSet < 0)
                {
                    offSet = 0;
                }

                byte[] buffer = intoBuffer;

                if (buffer != null)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        try
                        {
                            FileStream filesStream = new FileStream(Path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                            // 高興 9.3  判斷文件是否上傳完成 ,若是上傳完成,則更新上傳記錄XML
                            //若是沒完成
                            filesStream.Seek(offSet, SeekOrigin.Begin);
                            filesStream.Write(buffer, 0, buffer.Length);
                            filesStream.Flush();
                            //上傳完成
                            if (filesStream.Length >= FileLength)
                            {
                                filesStream.Close();
                                filesStream.Dispose();
                                Thread.Sleep(1000);
                                try
                                {
                                    //解壓 2012-09-25 ning 
                                    if (FileName.Split('.')[1].ToString() == "rar" || FileName.Split('.')[1].ToString() == "zip")
                                    {
                                        //Paths的值格式爲E:\New_Elearing\RescSyn\UpFiles\SCROM/flash/ 
                                        //FileName的值格式爲u8_demo.zip
                                        UnZip(Paths + FileName, Paths + FileName.Split('.')[0].ToString() + "/");
                                    }
                                    File.Delete(Paths + FileName);
                                    File.WriteAllText("D://SynOk.txt", Paths + "======" + FileName);
                                }
                                catch (Exception e)
                                {
                                    File.WriteAllText("D://SynUnOk.txt", e.Message.ToString());
                                }
                                //解壓
                            }
                            else
                            {
                                filesStream.Close();
                                filesStream.Dispose();
                            }
                            
                            return true;
                        }
                        catch { Thread.Sleep(100); }
                    }

                }
                else
                {
                }
                return false;
            }
        }
        public IAsyncResult BeginUploadFile(string strPath, long offSet, byte[] intoBuffer, string FullName, string Path,long FileLength, AsyncCallback ra, object state)
        {
            throw new NotImplementedException();
        }
        public bool EndUploadFile(IAsyncResult ra)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 獲取文件當前上傳的長度
        /// </summary>
        /// <param name="FileName">文件名</param>
        /// <param name="UploadType">上傳文件類型一、SCROM課程   二、ThreadSreen課程</param>
        /// <param name="UserId">用戶Id</param>
        /// <param name="PathNow">文件上傳相對路徑</param>
        /// <returns>長度</returns>
        public long GetFilesLength(string FileName, string Paths)
        {
            //string filePath = ConfigurationSettings.AppSettings["HostFileDirectory"].Trim() + "\\" + FileName;
            //string filePath = ConfigurationSettings.AppSettings["UploadFilePath"].ToString() + FileName;
            lock (this)
            {
                string filePath = "";
                filePath = Paths + FileName.Replace("\\", "").Replace("/","");

                if (File.Exists(filePath))
                {
                    using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
                    {
                        return fs.Length;
                    }
                }
                return 0;
            }
        }

        //傳入文件地址,若是不存在則建立
        /// <summary>
        /// 文件地址
        /// </summary>
        /// <param name="filePath"></param>
        public void NewFile(string filePath)
        {
            File.WriteAllText("d://path.txt", filePath);
            string[] arrS = filePath.Split('\\');
            string path = arrS[0].ToString();
            for (int i = 1; i < arrS.Length; i++)
            {
                if (arrS[i].ToString() != "")
                {
                    path += "\\" + arrS[i].ToString();
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }
                }
            }
        }

        /// <summary>
        /// 解壓文件
        /// </summary>
        /// <param name="SrcFile">壓縮包路徑</param>
        /// <param name="DstFile">要解壓的路徑</param>
        private void UnZip(string SrcFile, string DstFile)
        {
            //string SrcFile = @"D:\CM0103.zip";
            //string DstFile = @"D:\Temp\";
            string[] FileProperties = new string[2];
            FileProperties[0] = SrcFile;//待解壓的文件  
            FileProperties[1] = DstFile;//解壓後放置的目標目錄  
            UnZipClass UnZc = new UnZipClass();
            UnZc.UnZip(FileProperties);

        }

    }

    /// <summary>
    /// 解壓文件類
    /// </summary>
    public class UnZipClass
    {
        public void UnZip(string[] args)
        {
            ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]));

            ZipEntry theEntry;
            while ((theEntry = s.GetNextEntry()) != null)
            {

                string directoryName = Path.GetDirectoryName(args[1]);
                string fileName = Path.GetFileName(theEntry.Name);

                //生成解壓目錄  
                //Directory.CreateDirectory(directoryName);

                if (!Directory.Exists(directoryName))
                {
                    Directory.CreateDirectory(directoryName);
                }

                if (fileName != String.Empty)
                {
                    string filePath = (args[1] + theEntry.Name).Replace(fileName, "");
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    //解壓文件到指定的目錄  
                    FileStream streamWriter = File.Create((args[1] + theEntry.Name).Replace("'",""));

                    int size = 2048;
                    byte[] data = new byte[2048];
                    while (true)
                    {
                        size = s.Read(data, 0, data.Length);
                        if (size > 0)
                        {
                            streamWriter.Write(data, 0, size);
                        }
                        else
                        {
                            break;
                        }
                    }

                    streamWriter.Close();
                }
            }
            s.Close();
        }
    }
}
相關文章
相關標籤/搜索