WCF传输大数据 --断点续传(upload、download)
1 using System; 2 using System.IO; 3 using System.Runtime.Serialization; 4 using System.ServiceModel; 5 6 namespace WcfServer 7 { 8 internal class Program 9 { 10 private static void Main() 11 { 12 using (var host = new ServiceHost(typeof (StreamServices))) 13 { 14 host.Opened += (a, b) => Console.WriteLine("..."); 15 host.Open(); 16 17 Console.ReadKey(); 18 } 19 } 20 } 21 22 [ServiceContract(Name = "IStreamServices", 23 SessionMode = SessionMode.Required, 24 Namespace = "http://www.msdn.com/IStreamServices/14/04/11")] 25 public interface IStreamServices 26 { 27 [OperationContract(Name = "Upload")] 28 FileInformation Upload(FileInformation fileInfo); 29 30 [OperationContract(Name = "Download")] 31 FileInformation Download(FileInformation fileInfo); 32 } 33 34 [ServiceBehavior(Name = "StreamServices", 35 Namespace = "http://www.msdn.com/StreamServices/14/04/11" 36 , InstanceContextMode = InstanceContextMode.PerCall, 37 ConcurrencyMode = ConcurrencyMode.Multiple)] 38 public class StreamServices : IStreamServices 39 { 40 private static readonly string AttachmentPath = AppDomain.CurrentDomain.BaseDirectory + "Attachments//"; 41 42 #region IServices 成员 43 44 public FileInformation Upload(FileInformation fileInfo) 45 { 46 try 47 { 48 if (fileInfo == null) 49 return new FileInformation {Error = "FileInformation对象不能为空"}; 50 if (string.IsNullOrEmpty(fileInfo.FileNameNew)) 51 fileInfo.FileNameNew = Guid.NewGuid() + fileInfo.FileSuffix; 52 var savePath = AttachmentPath + fileInfo.FileNameNew; 53 using (var fs = new FileStream(savePath, FileMode.OpenOrCreate)) 54 { 55 long offset = fileInfo.Offset; 56 using (var write = new BinaryWriter(fs)) 57 { 58 write.Seek((int) offset, SeekOrigin.Begin); 59 write.Write(fileInfo.Data); 60 fileInfo.Offset = fs.Length; 61 } 62 } 63 return fileInfo; 64 } 65 catch (IOException ex) 66 { 67 return new FileInformation {Error = ex.Message}; 68 } 69 catch (Exception ex) 70 { 71 System.Diagnostics.Debug.WriteLine(ex.Message); 72 return new FileInformation {Error = "wcf内部错误"}; 73 } 74 } 75 76 public FileInformation Download(FileInformation fileInfo) 77 { 78 try 79 { 80 if (fileInfo == null) 81 return new FileInformation {Error = "FileInformation对象不能为空"}; 82 var readFileName = AttachmentPath + fileInfo.FileName; 83 if (!File.Exists(readFileName)) 84 return new FileInformation {Error = "DirectoryNotFoundException"}; 85 var stream = File.OpenRead(readFileName); 86 fileInfo.Length = stream.Length; 87 if (fileInfo.Offset.Equals(fileInfo.Length)) 88 return new FileInformation {Offset = fileInfo.Offset, Length = stream.Length}; 89 var maxSize = fileInfo.MaxSize > 1024*500 ? 1024*300 : fileInfo.MaxSize; 90 fileInfo.Data = 91 new byte[fileInfo.Length - fileInfo.Offset <= maxSize ? fileInfo.Length - fileInfo.Offset : maxSize]; 92 stream.Position = fileInfo.Offset; 93 stream.Read(fileInfo.Data, 0, fileInfo.Data.Length); 94 return fileInfo; 95 } 96 catch (IOException ex) 97 { 98 return new FileInformation {Error = ex.Message}; 99 } 100 catch (Exception ex) 101 { 102 System.Diagnostics.Debug.WriteLine(ex.Message); 103 return new FileInformation {Error = "wcf内部错误"}; 104 } 105 } 106 107 #endregion 108 } 109 110 [DataContract(Name = "MyStreamInfo")] 111 public class FileInformation 112 { 113 [DataMember(Name = "Length", IsRequired = true)] 114 public long Length { get; set; } 115 116 [DataMember(Name = "FileName", IsRequired = true)] 117 public string FileName { get; set; } 118 119 [DataMember(Name = "Data")] 120 public byte[] Data { get; set; } 121 122 [DataMember(Name = "FileSuffix")] 123 public string FileSuffix { get; set; } 124 125 [DataMember(Name = "Offset", IsRequired = true)] 126 public long Offset { get; set; } 127 128 [DataMember(Name = "Error")] 129 public string Error { get; set; } 130 131 private int maxSize = 1024*200; //200k 132 133 [DataMember(Name = "MaxSize")] 134 public int MaxSize 135 { 136 get { return maxSize; } 137 set { maxSize = value; } 138 } 139 140 [DataMember(Name = "KeyToken")] 141 public string KeyToken { get; set; } 142 143 [DataMember(Name = "FileNameNew")] 144 public string FileNameNew { get; set; } 145 } 146 }
1 using System; 2 using System.IO; 3 using WcfClientApp.ServiceReference1; 4 5 namespace WcfClientApp 6 { 7 internal class Program 8 { 9 private static void Main() 10 { 11 Upload(); 12 Download(); 13 Console.ReadKey(); 14 } 15 16 /// <summary> 17 /// 上传 18 /// </summary> 19 private static void Upload() 20 { 21 try 22 { 23 var filePath = AppDomain.CurrentDomain.BaseDirectory + "UploadFiles//张国荣 - 共同度过.mp3"; 24 const string fileName = "张国荣 - 共同度过.mp3"; 25 const int maxSize = 1024*200; 26 if (!File.Exists(filePath)) 27 { 28 Console.WriteLine("DirectoryNotFoundException"); 29 return; 30 } 31 FileStream stream = File.OpenRead(filePath); 32 var fileInfo = new MyStreamInfo {Length = stream.Length, FileName = fileName,FileSuffix=".mp3"}; 33 using (var client = new StreamServicesClient()) 34 { 35 while (fileInfo.Length != fileInfo.Offset) 36 { 37 fileInfo.Data = 38 new byte[ 39 fileInfo.Length - fileInfo.Offset <= maxSize 40 ? fileInfo.Length - fileInfo.Offset 41 : maxSize]; 42 stream.Position = fileInfo.Offset; 43 stream.Read(fileInfo.Data, 0, fileInfo.Data.Length); 44 fileInfo = client.Upload(fileInfo); 45 if (!string.IsNullOrEmpty(fileInfo.Error)) 46 { 47 Console.WriteLine(fileInfo.Error); 48 break; 49 } 50 } 51 if (fileInfo.Length.Equals(fileInfo.Offset)) 52 Console.WriteLine("Upload successful!"); 53 } 54 } 55 catch (Exception ex) 56 { 57 Console.WriteLine(ex.Message); 58 } 59 } 60 /// <summary> 61 /// 下载 62 /// </summary> 63 private static void Download() 64 { 65 try 66 { 67 var filePath = AppDomain.CurrentDomain.BaseDirectory + 68 "DownloadFiles//c228d4df-8bdc-468b-96ec-46860c2f026a.mp3"; 69 const string fileName = "c228d4df-8bdc-468b-96ec-46860c2f026a.mp3"; 70 var fileInfo = new MyStreamInfo {FileName = fileName, Length = 1, MaxSize = 1024*200}; 71 using (var client = new StreamServicesClient()) 72 { 73 while (fileInfo.Length != fileInfo.Offset) 74 { 75 fileInfo = client.Download(fileInfo); 76 if (!string.IsNullOrEmpty(fileInfo.Error)) 77 { 78 Console.WriteLine(fileInfo.Error); 79 break; 80 } 81 using (var fs = new FileStream(filePath, FileMode.OpenOrCreate)) 82 { 83 long offset = fileInfo.Offset; 84 using (var write = new BinaryWriter(fs)) 85 { 86 write.Seek((int) offset, SeekOrigin.Begin); 87 write.Write(fileInfo.Data); 88 fileInfo.Offset = fs.Length; 89 } 90 } 91 } 92 if (fileInfo.Length.Equals(fileInfo.Offset)) 93 Console.WriteLine("download successful!"); 94 } 95 } 96 catch (Exception ex) 97 { 98 Console.WriteLine(ex.Message); 99 } 100 } 101 } 102 }
使用MaxSize控制下载、上传大小(k)
一开始设计的时候,我考虑使用双工模式,但是觉得有不太好,使用双工模式反而增加了代码开发量。
不知道各位有没有什么更好的解决办法?是否愿意分享一下,谢谢各位的指点。