From 6a0244e95ff15b58cfc269fa69ad7dd0164ba909 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 18 Feb 2014 15:05:46 +0800 Subject: [PATCH 01/16] Update README.md --- Docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/README.md b/Docs/README.md index 407ad2bf..70a011e5 100644 --- a/Docs/README.md +++ b/Docs/README.md @@ -498,7 +498,7 @@ public event EventHandler NotifyErr; 其中是bucket所对应的域名。七牛云存储为每一个bucket提供一个默认域名。默认域名可以到[七牛云存储开发者平台](https://portal.qiniu.com/)中,空间设置的域名设置一节查询。用户也可以将自有的域名绑定到bucket上,用户可以通过自有域名访问七牛云存储。 -**注意: key必须采用utf8编码,如使用非utf8编码访问七牛云存储将反馈错误** +**注意: key必须采用utf8编码,如使用非utf8编码访问七牛云存储将返回错误** #### 私有资源下载 From f00da7ad4343cf3bacbcbae8d7142333d2baefea Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Thu, 20 Feb 2014 14:03:43 +0800 Subject: [PATCH 02/16] Enhance resumable Put --- Qiniu/IO/Resumable/ResumablePut.cs | 81 +++++++-------------- Qiniu/IO/Resumable/ResumablePutHelper.cs | 87 +++++++++++++++++++++++ Qiniu/IO/Resumable/ResumablePutRet.cs | 2 +- Qiniu/IO/Resumable/Settings.cs | 5 +- Qiniu/Qiniu.2.0.csproj | 1 + Qiniu/Qiniu.4.0.csproj | 3 +- bin/Qiniu.2.0.dll | Bin 0 -> 45568 bytes bin/Qiniu.4.0.dll | Bin 46080 -> 46080 bytes csharp-sdk.2.0.sln | 4 +- 9 files changed, 120 insertions(+), 63 deletions(-) create mode 100644 Qiniu/IO/Resumable/ResumablePutHelper.cs create mode 100755 bin/Qiniu.2.0.dll diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 22893e0a..9a219701 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Generic; using System.IO; using System.Text; #if NET40 @@ -88,6 +89,10 @@ public CallRet PutFile(string upToken, string localFile, string key) { throw new Exception(string.Format("{0} does not exist", localFile)); } + + string puttedFile = ResumbalePutHelper.GetPutHistroryFile(localFile); + Dictionary puttedBlk = ResumbalePutHelper.GetHistory(puttedFile); + PutAuthClient client = new PutAuthClient(upToken); CallRet ret; using (FileStream fs = File.OpenRead(localFile)) @@ -97,26 +102,20 @@ public CallRet PutFile(string upToken, string localFile, string key) chunks = fsize / extra.chunkSize + 1; extra.Progresses = new BlkputRet[block_cnt]; //并行上传 -#if NET35||NET20 for (int i = 0; i < block_cnt; i++) { -#elif NET40 - Parallel.For(0, block_cnt, (i) =>{ -#endif - + if (puttedBlk != null && puttedBlk.ContainsKey(i) && puttedBlk[i] != null) + { + Console.WriteLine(string.Format("block{0} has putted", i)); + extra.Progresses[i] = puttedBlk[i]; + continue; + } int readLen = BLOCKSIZE; if ((i + 1) * BLOCKSIZE > fsize) readLen = (int)(fsize - i * BLOCKSIZE); byte[] byteBuf = new byte[readLen]; -#if NET40 - lock (fs) - { -#endif fs.Seek(i * BLOCKSIZE, SeekOrigin.Begin); fs.Read(byteBuf, 0, readLen); -#if NET40 - } -#endif //并行上传BLOCK BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen); if (blkRet == null) @@ -125,15 +124,12 @@ public CallRet PutFile(string upToken, string localFile, string key) } else { + ResumbalePutHelper.Append(puttedFile, i, blkRet); extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); } -#if NET35||NET20 } -#elif NET40 - }); -#endif ret = Mkfile(client, key, fs.Length); - } + } if (ret.OK) { if (Progress != null) @@ -181,34 +177,19 @@ private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int uint crc32 = CRC32.CheckSumBytes(firstChunk); for (int i = 0; i < putSetting.TryTimes; i++) { - extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); - if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) + try + { + extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); + } + catch (Exception ee) { if (i == (putSetting.TryTimes - 1)) { - return null; + throw ee; } continue; - } - else - { - progress(); - break; - } - } - } - #endregion - - #region PutBlock - while (extra.Progresses[blkIdex].offset < blkSize) - { - bodyLength = (chunkSize < (blkSize - extra.Progresses[blkIdex].offset)) ? chunkSize : (int)(blkSize - extra.Progresses[blkIdex].offset); - byte[] chunk = new byte[bodyLength]; - Array.Copy(body, extra.Progresses[blkIdex].offset, chunk, 0, bodyLength); - for (int i = 0; i < putSetting.TryTimes; i++) - { - extra.Progresses[blkIdex] = BlockPut(client, extra.Progresses[blkIdex], new MemoryStream(chunk), bodyLength); - if (extra.Progresses[blkIdex] == null) + } + if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) { if (i == (putSetting.TryTimes - 1)) { @@ -218,11 +199,7 @@ private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int } else { - uploadedChunks++; - if (Progress != null) - { - Progress((float)uploadedChunks / chunks); - } + progress(); break; } } @@ -230,6 +207,7 @@ private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int #endregion return extra.Progresses[blkIdex]; } + private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) { @@ -242,17 +220,6 @@ private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) return null; } - private BlkputRet BlockPut(Client client, BlkputRet ret, Stream body, long length) - { - string url = string.Format("{0}/bput/{1}/{2}", Config.UP_HOST, ret.ctx, ret.offset); - CallRet callRet = client.CallWithBinary(url, "application/octet-stream", body, length); - if (callRet.OK) - { - return QiniuJsonHelper.ToObject(callRet.Response); - } - return null; - } - private CallRet Mkfile(Client client, string key, long fsize) { StringBuilder urlBuilder = new StringBuilder(); diff --git a/Qiniu/IO/Resumable/ResumablePutHelper.cs b/Qiniu/IO/Resumable/ResumablePutHelper.cs new file mode 100644 index 00000000..20e2d5a9 --- /dev/null +++ b/Qiniu/IO/Resumable/ResumablePutHelper.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.IO; +using System.IO.Compression; +using Qiniu.IO.Resumable; +namespace Qiniu +{ + public static class ResumbalePutHelper + { + public static Dictionary GetHistory(string filename) + { + return ParseHistory(filename); + } + + /// + /// File Format: + /// i,offset,ctx/n + /// i,offset,ctx/n + /// + /// + public static Dictionary ParseHistory(string tempFile) + { + if (!File.Exists(tempFile)) + { + return null; + } + string[] lines = File.ReadAllLines(tempFile); + Dictionary result = new Dictionary(); + foreach (string line in lines) + { + string[] fields = line.Split(','); + BlkputRet ret = new BlkputRet(); + ret.offset = ulong.Parse(fields[1]); + ret.ctx = fields[2]; + int idx = int.Parse(fields[0]); + result.Add(idx, ret); + } + return result; + } + + /// + /// + /// + /// + /// + /// + public static void Append(string tempFileName, int idx, BlkputRet ret) + { + string content = idx + "," + ret.offset + "," + ret.ctx + "\n"; + File.AppendAllText(tempFileName, content); + } + + /// + /// ȡļSHA1ֵ + /// + /// + /// base64sha1ֵ + public static string GetFileBase64Sha1(string filename) + { + SHA1 sha1 = new SHA1CryptoServiceProvider(); + using (Stream reader = System.IO.File.OpenRead(filename)) + { + byte[] result = sha1.ComputeHash(reader); + return BitConverter.ToString(result); + } + } + + /// + /// ȡʱļ + /// + /// + /// + public static string GetTempleFile(string filename) + { + string tempPath = Path.GetTempPath(); + return tempPath + filename; + } + + public static string GetPutHistroryFile(string filename) { + + string f = GetFileBase64Sha1(filename); + return GetTempleFile(f); + } + } +} + diff --git a/Qiniu/IO/Resumable/ResumablePutRet.cs b/Qiniu/IO/Resumable/ResumablePutRet.cs index e7dfa6d0..a04828e2 100644 --- a/Qiniu/IO/Resumable/ResumablePutRet.cs +++ b/Qiniu/IO/Resumable/ResumablePutRet.cs @@ -13,6 +13,6 @@ public class BlkputRet [JsonProperty("crc32")] public UInt32 crc32; [JsonProperty("offset")] - public UInt32 offset; + public ulong offset; } } diff --git a/Qiniu/IO/Resumable/Settings.cs b/Qiniu/IO/Resumable/Settings.cs index 63331210..4c98e784 100644 --- a/Qiniu/IO/Resumable/Settings.cs +++ b/Qiniu/IO/Resumable/Settings.cs @@ -32,8 +32,9 @@ public int TryTimes { /// chunk大小,默认为4MB /// 失败重试次数,默认为3 public Settings (int chunkSize=1 << 22, int tryTimes=3) - { - this.chunkSize = chunkSize; + { + //取消chunk + this.chunkSize = 1 << 22; this.tryTimes = tryTimes; } } diff --git a/Qiniu/Qiniu.2.0.csproj b/Qiniu/Qiniu.2.0.csproj index 00539836..6c73fbde 100644 --- a/Qiniu/Qiniu.2.0.csproj +++ b/Qiniu/Qiniu.2.0.csproj @@ -53,6 +53,7 @@ + diff --git a/Qiniu/Qiniu.4.0.csproj b/Qiniu/Qiniu.4.0.csproj index 1734a9af..ee882863 100644 --- a/Qiniu/Qiniu.4.0.csproj +++ b/Qiniu/Qiniu.4.0.csproj @@ -53,6 +53,7 @@ + @@ -102,4 +103,4 @@ - + \ No newline at end of file diff --git a/bin/Qiniu.2.0.dll b/bin/Qiniu.2.0.dll new file mode 100755 index 0000000000000000000000000000000000000000..4202a94683581254b799e41d4a48518312837972 GIT binary patch literal 45568 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 Date: Tue, 25 Feb 2014 13:36:48 +0800 Subject: [PATCH 03/16] fix Resumble Upload --- Docs/README.md | 2 +- Qiniu/IO/Resumable/ResumablePut.cs | 529 +++++++++++++++-------------- Qiniu/Qiniu.2.0.csproj | 2 +- Qiniu/Qiniu.4.0.csproj | 2 +- csharp-sdk.4.0.sln | 4 +- 5 files changed, 274 insertions(+), 265 deletions(-) diff --git a/Docs/README.md b/Docs/README.md index 70a011e5..a8944883 100644 --- a/Docs/README.md +++ b/Docs/README.md @@ -424,7 +424,7 @@ public static void PutFile(string bucket, string key, string fname) { var policy = new PutPolicy(bucket, 3600); string upToken = policy.Token(); - PutExtra extra = new PutExtra { Bucket = bucket }; + PutExtra extra = new PutExtra(); IOClient client = new IOClient(); client.PutFinished += new EventHandler((o, ret) => { if (ret.OK) diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 9a219701..0b864d66 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -9,263 +9,272 @@ using Qiniu.Conf; using Qiniu.RPC; using Qiniu.RS; -using Qiniu.Util; - -namespace Qiniu.IO.Resumable -{ - /// - /// 异步并行断点上传类 - /// - public class ResumablePut - { - private const int blockBits = 22; - private const int blockMashk = (1 << blockBits) - 1; - private static int BLOCKSIZE = 4 * 1024 * 1024; - - #region 记录总文件大小,用于计算上传百分比 - - private long fsize; - private float chunks; - private float uploadedChunks = 0; - - #endregion - - /// - /// 上传完成事件 - /// - public event EventHandler PutFinished; - /// - /// 上传Failure事件 - /// - public event EventHandler PutFailure; - /// - /// 进度提示事件 - /// - public event Action Progress; - - Settings putSetting; - - /// - /// 上传设置 - /// - public Settings PutSetting - { - get { return putSetting; } - set { putSetting = value; } - } - - ResumablePutExtra extra; - - /// - /// PutExtra - /// - public ResumablePutExtra Extra - { - get { return extra; } - set { extra = value; } - } - - /// - /// 断点续传类 - /// - /// - /// - public ResumablePut(Settings putSetting, ResumablePutExtra extra) - { - extra.chunkSize = putSetting.ChunkSize; - this.putSetting = putSetting; - this.extra = extra; - } - - /// - /// 上传文件 - /// - /// 上传Token - /// key - /// 本地文件名 - public CallRet PutFile(string upToken, string localFile, string key) - { - if (!File.Exists(localFile)) - { - throw new Exception(string.Format("{0} does not exist", localFile)); - } - - string puttedFile = ResumbalePutHelper.GetPutHistroryFile(localFile); - Dictionary puttedBlk = ResumbalePutHelper.GetHistory(puttedFile); - - PutAuthClient client = new PutAuthClient(upToken); - CallRet ret; - using (FileStream fs = File.OpenRead(localFile)) - { - int block_cnt = block_count(fs.Length); - fsize = fs.Length; - chunks = fsize / extra.chunkSize + 1; - extra.Progresses = new BlkputRet[block_cnt]; - //并行上传 - for (int i = 0; i < block_cnt; i++) - { - if (puttedBlk != null && puttedBlk.ContainsKey(i) && puttedBlk[i] != null) - { - Console.WriteLine(string.Format("block{0} has putted", i)); - extra.Progresses[i] = puttedBlk[i]; - continue; - } - int readLen = BLOCKSIZE; - if ((i + 1) * BLOCKSIZE > fsize) - readLen = (int)(fsize - i * BLOCKSIZE); - byte[] byteBuf = new byte[readLen]; - fs.Seek(i * BLOCKSIZE, SeekOrigin.Begin); - fs.Read(byteBuf, 0, readLen); - //并行上传BLOCK - BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen); - if (blkRet == null) - { - extra.OnNotifyErr(new PutNotifyErrorEvent(i, readLen, "Make Block Error")); - } - else - { - ResumbalePutHelper.Append(puttedFile, i, blkRet); - extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); - } - } - ret = Mkfile(client, key, fs.Length); - } - if (ret.OK) - { - if (Progress != null) - { - Progress(1.0f); - } - if (PutFinished != null) - { - PutFinished(this, ret); - } - } - else - { - if (PutFailure != null) - { - PutFailure(this, ret); - } - } - return ret; - } - - - /// - /// 百分比进度提示 - /// - private void progress() - { - uploadedChunks++; - if (Progress != null) - { - Progress((float)uploadedChunks / chunks); - } - } - - private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int blkSize) - { - int bodyLength; - int chunkSize = extra.chunkSize; - #region Mkblock - if (extra.Progresses[blkIdex] == null) - { - bodyLength = chunkSize < blkSize ? chunkSize : blkSize; - byte[] firstChunk = new byte[bodyLength]; - Array.Copy(body, 0, firstChunk, 0, bodyLength); - uint crc32 = CRC32.CheckSumBytes(firstChunk); - for (int i = 0; i < putSetting.TryTimes; i++) - { - try - { - extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); - } - catch (Exception ee) - { - if (i == (putSetting.TryTimes - 1)) - { - throw ee; - } - continue; - } - if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) - { - if (i == (putSetting.TryTimes - 1)) - { - return null; - } - continue; - } - else - { - progress(); - break; - } - } - } - #endregion - return extra.Progresses[blkIdex]; - } - - - private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) - { - string url = string.Format("{0}/mkblk/{1}", Config.UP_HOST, blkSize); - CallRet callRet = client.CallWithBinary(url, "application/octet-stream", new MemoryStream(firstChunk), firstChunk.Length); - if (callRet.OK) - { - return QiniuJsonHelper.ToObject(callRet.Response); - } - return null; - } - - private CallRet Mkfile(Client client, string key, long fsize) - { - StringBuilder urlBuilder = new StringBuilder(); - urlBuilder.AppendFormat("{0}/mkfile/{1}", Config.UP_HOST, fsize); - if (key != null) - { - urlBuilder.AppendFormat("/key/{0}", Base64URLSafe.ToBase64URLSafe(key)); - } - if (!string.IsNullOrEmpty(extra.MimeType)) - { - urlBuilder.AppendFormat("/mimeType/{0}", Base64URLSafe.ToBase64URLSafe(extra.MimeType)); - } - if (!string.IsNullOrEmpty(extra.CustomMeta)) - { - urlBuilder.AppendFormat("/meta/{0}", Base64URLSafe.ToBase64URLSafe(extra.CustomMeta)); - } - if (extra.CallbackParams != null && extra.CallbackParams.Count > 0) - { - StringBuilder sb = new StringBuilder(); - foreach (string _key in extra.CallbackParams.Keys) - { - sb.AppendFormat("/{0}/{1}", _key, Base64URLSafe.ToBase64URLSafe(extra.CallbackParams[_key])); - } - urlBuilder.Append(sb.ToString()); - } - - int proCount = extra.Progresses.Length; - using (Stream body = new MemoryStream()) - { - for (int i = 0; i < proCount; i++) - { - byte[] bctx = Encoding.ASCII.GetBytes(extra.Progresses[i].ctx); - body.Write(bctx, 0, bctx.Length); - if (i != proCount - 1) - { - body.WriteByte((byte)','); - } - } - body.Seek(0, SeekOrigin.Begin); - return client.CallWithBinary(urlBuilder.ToString(), "text/plain", body, body.Length); - } - } - - private int block_count(long fsize) - { - return (int)((fsize + blockMashk) >> blockBits); - } - } +using Qiniu.Util; + +namespace Qiniu.IO.Resumable +{ + /// + /// 异步并行断点上传类 + /// + public class ResumablePut + { + private const int blockBits = 22; + private const int blockMashk = (1 << blockBits) - 1; + private static int BLOCKSIZE = 4 * 1024 * 1024; + + #region 记录总文件大小,用于计算上传百分比 + + private long fsize; + private float chunks; + private float uploadedChunks = 0; + + #endregion + + /// + /// 上传完成事件 + /// + public event EventHandler PutFinished; + /// + /// 上传Failure事件 + /// + public event EventHandler PutFailure; + /// + /// 进度提示事件 + /// + public event Action Progress; + + Settings putSetting; + + /// + /// 上传设置 + /// + public Settings PutSetting + { + get { return putSetting; } + set { putSetting = value; } + } + + ResumablePutExtra extra; + + /// + /// PutExtra + /// + public ResumablePutExtra Extra + { + get { return extra; } + set { extra = value; } + } + + /// + /// 断点续传类 + /// + /// + /// + public ResumablePut(Settings putSetting, ResumablePutExtra extra) + { + extra.chunkSize = putSetting.ChunkSize; + this.putSetting = putSetting; + this.extra = extra; + } + + /// + /// 上传文件 + /// + /// 上传Token + /// key + /// 本地文件名 + public CallRet PutFile(string upToken, string localFile, string key) + { + if (!File.Exists(localFile)) + { + throw new Exception(string.Format("{0} does not exist", localFile)); + } + string puttedFile = string.Empty; + Dictionary puttedBlk = new Dictionary (); + if (extra.AllowCahce) { + puttedFile = ResumbalePutHelper.GetPutHistroryFile (localFile); + puttedBlk = ResumbalePutHelper.GetHistory (puttedFile); + } + PutAuthClient client = new PutAuthClient(upToken); + CallRet ret; + using (FileStream fs = File.OpenRead(localFile)) + { + int block_cnt = block_count(fs.Length); + fsize = fs.Length; + chunks = fsize / extra.chunkSize + 1; + extra.Progresses = new BlkputRet[block_cnt]; + //并行上传 + for (int i = 0; i < block_cnt; i++) + { + + if (extra.AllowCahce && puttedBlk != null && puttedBlk.ContainsKey(i) && puttedBlk[i] != null) + { + Console.WriteLine(string.Format("block{0} has putted", i)); + extra.Progresses[i] = puttedBlk[i]; + continue; + } + int readLen = BLOCKSIZE; + if ((long)(i + 1) * BLOCKSIZE > fsize) + readLen = (int)(fsize - (long)i * BLOCKSIZE); + byte[] byteBuf = new byte[readLen]; + fs.Seek((long)i* BLOCKSIZE, SeekOrigin.Begin); + fs.Read(byteBuf, 0, readLen); + //并行上传BLOCK + BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen); + if (blkRet == null) + { + extra.OnNotifyErr(new PutNotifyErrorEvent(i, readLen, "Make Block Error")); + } + else + { + if (extra.AllowCahce) + { + ResumbalePutHelper.Append (puttedFile, i, blkRet); + } + extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); + } + } + ret = Mkfile(client, key, fs.Length); + } + if (ret.OK) + { + if (Progress != null) + { + Progress(1.0f); + } + if (PutFinished != null) + { + PutFinished(this, ret); + } + } + else + { + if (PutFailure != null) + { + PutFailure(this, ret); + } + } + return ret; + } + + + /// + /// 百分比进度提示 + /// + private void progress() + { + uploadedChunks++; + if (Progress != null) + { + Progress((float)uploadedChunks / chunks); + } + } + + private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int blkSize) + { + int bodyLength; + int chunkSize = extra.chunkSize; + #region Mkblock + if (extra.Progresses[blkIdex] == null) + { + bodyLength = chunkSize < blkSize ? chunkSize : blkSize; + byte[] firstChunk = new byte[bodyLength]; + Array.Copy(body, 0, firstChunk, 0, bodyLength); + uint crc32 = CRC32.CheckSumBytes(firstChunk); + for (int i = 0; i < putSetting.TryTimes; i++) + { + try + { + extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); + } + catch (Exception ee) + { + if (i == (putSetting.TryTimes - 1)) + { + throw ee; + } + System.Threading.Thread.Sleep(1000); + continue; + } + if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) + { + if (i == (putSetting.TryTimes - 1)) + { + return null; + } + System.Threading.Thread.Sleep(1000); + continue; + } + else + { + progress(); + break; + } + } + } + #endregion + + return extra.Progresses[blkIdex]; + } + + + private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) + { + string url = string.Format("{0}/mkblk/{1}", Config.UP_HOST, blkSize); + CallRet callRet = client.CallWithBinary(url, "application/octet-stream", new MemoryStream(firstChunk), firstChunk.Length); + if (callRet.OK) + { + return QiniuJsonHelper.ToObject(callRet.Response); + } + return null; + } + + private CallRet Mkfile(Client client, string key, long fsize) + { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.AppendFormat("{0}/mkfile/{1}", Config.UP_HOST, fsize); + if (key != null) + { + urlBuilder.AppendFormat("/key/{0}", Base64URLSafe.ToBase64URLSafe(key)); + } + if (!string.IsNullOrEmpty(extra.MimeType)) + { + urlBuilder.AppendFormat("/mimeType/{0}", Base64URLSafe.ToBase64URLSafe(extra.MimeType)); + } + if (!string.IsNullOrEmpty(extra.CustomMeta)) + { + urlBuilder.AppendFormat("/meta/{0}", Base64URLSafe.ToBase64URLSafe(extra.CustomMeta)); + } + if (extra.CallbackParams != null && extra.CallbackParams.Count > 0) + { + StringBuilder sb = new StringBuilder(); + foreach (string _key in extra.CallbackParams.Keys) + { + sb.AppendFormat("/{0}/{1}", _key, Base64URLSafe.ToBase64URLSafe(extra.CallbackParams[_key])); + } + urlBuilder.Append(sb.ToString()); + } + + int proCount = extra.Progresses.Length; + using (Stream body = new MemoryStream()) + { + for (int i = 0; i < proCount; i++) + { + byte[] bctx = Encoding.ASCII.GetBytes(extra.Progresses[i].ctx); + body.Write(bctx, 0, bctx.Length); + if (i != proCount - 1) + { + body.WriteByte((byte)','); + } + } + body.Seek(0, SeekOrigin.Begin); + return client.CallWithBinary(urlBuilder.ToString(), "text/plain", body, body.Length); + } + } + + private int block_count(long fsize) + { + return (int)((fsize + blockMashk) >> blockBits); + } + } } diff --git a/Qiniu/Qiniu.2.0.csproj b/Qiniu/Qiniu.2.0.csproj index 6c73fbde..b5e9df3e 100644 --- a/Qiniu/Qiniu.2.0.csproj +++ b/Qiniu/Qiniu.2.0.csproj @@ -15,7 +15,7 @@ - x86 + AnyCPU true full false diff --git a/Qiniu/Qiniu.4.0.csproj b/Qiniu/Qiniu.4.0.csproj index ee882863..43ffa972 100644 --- a/Qiniu/Qiniu.4.0.csproj +++ b/Qiniu/Qiniu.4.0.csproj @@ -15,7 +15,7 @@ - x86 + AnyCPU true full false diff --git a/csharp-sdk.4.0.sln b/csharp-sdk.4.0.sln index a98455bc..7d25e03f 100644 --- a/csharp-sdk.4.0.sln +++ b/csharp-sdk.4.0.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SDK", "SDK", "{65603FA4-DDC3-4FD7-ADA3-7BCC2161A247}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu", "Qiniu\Qiniu.4.0.csproj", "{AD4EA9D1-11C2-4BF6-8A06-72A966BC1B80}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.4.0", "Qiniu\Qiniu.4.0.csproj", "{AD4EA9D1-11C2-4BF6-8A06-72A966BC1B80}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.Test", "Qiniu.Test\Qiniu.4.0.Test.csproj", "{95DC2A77-2344-4315-9F6F-334CC928459C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.4.0.Test", "Qiniu.Test\Qiniu.4.0.Test.csproj", "{95DC2A77-2344-4315-9F6F-334CC928459C}" EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution From efcaf4476c681f24a10f11c15d680d532c297e3f Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Tue, 25 Feb 2014 13:46:27 +0800 Subject: [PATCH 04/16] fix resumbel upload --- CHANGELOG.md | 8 + Qiniu/IO/Resumable/ResumablePut.cs | 544 +++++++++++++++-------------- bin/Qiniu.2.0.dll | Bin 45568 -> 46592 bytes bin/Qiniu.4.0.dll | Bin 46080 -> 46592 bytes 4 files changed, 284 insertions(+), 268 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df7c3fb6..d156d45f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## CHANGE LOG + +### v6.1.1 +2014-02-25 issue [#41](https://github.com/qiniu/csharp-sdk/pull/41) + +- 简化断点续上传,删除bput逻辑 +- 增加断点续上传中块上传结果本地缓存特性 +- 修复bug:>2.5GB文件上传失败 + ### v6.1.0 2014-02-18 issue [#37](https://github.com/qiniu/csharp-sdk/pull/37) diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 0b864d66..826df04b 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -9,272 +9,280 @@ using Qiniu.Conf; using Qiniu.RPC; using Qiniu.RS; -using Qiniu.Util; - -namespace Qiniu.IO.Resumable -{ - /// - /// 异步并行断点上传类 - /// - public class ResumablePut - { - private const int blockBits = 22; - private const int blockMashk = (1 << blockBits) - 1; - private static int BLOCKSIZE = 4 * 1024 * 1024; - - #region 记录总文件大小,用于计算上传百分比 - - private long fsize; - private float chunks; - private float uploadedChunks = 0; - - #endregion - - /// - /// 上传完成事件 - /// - public event EventHandler PutFinished; - /// - /// 上传Failure事件 - /// - public event EventHandler PutFailure; - /// - /// 进度提示事件 - /// - public event Action Progress; - - Settings putSetting; - - /// - /// 上传设置 - /// - public Settings PutSetting - { - get { return putSetting; } - set { putSetting = value; } - } - - ResumablePutExtra extra; - - /// - /// PutExtra - /// - public ResumablePutExtra Extra - { - get { return extra; } - set { extra = value; } - } - - /// - /// 断点续传类 - /// - /// - /// - public ResumablePut(Settings putSetting, ResumablePutExtra extra) - { - extra.chunkSize = putSetting.ChunkSize; - this.putSetting = putSetting; - this.extra = extra; - } - - /// - /// 上传文件 - /// - /// 上传Token - /// key - /// 本地文件名 - public CallRet PutFile(string upToken, string localFile, string key) - { - if (!File.Exists(localFile)) - { - throw new Exception(string.Format("{0} does not exist", localFile)); - } - string puttedFile = string.Empty; - Dictionary puttedBlk = new Dictionary (); - if (extra.AllowCahce) { - puttedFile = ResumbalePutHelper.GetPutHistroryFile (localFile); - puttedBlk = ResumbalePutHelper.GetHistory (puttedFile); - } - PutAuthClient client = new PutAuthClient(upToken); - CallRet ret; - using (FileStream fs = File.OpenRead(localFile)) - { - int block_cnt = block_count(fs.Length); - fsize = fs.Length; - chunks = fsize / extra.chunkSize + 1; - extra.Progresses = new BlkputRet[block_cnt]; - //并行上传 - for (int i = 0; i < block_cnt; i++) - { - - if (extra.AllowCahce && puttedBlk != null && puttedBlk.ContainsKey(i) && puttedBlk[i] != null) - { - Console.WriteLine(string.Format("block{0} has putted", i)); - extra.Progresses[i] = puttedBlk[i]; - continue; - } - int readLen = BLOCKSIZE; - if ((long)(i + 1) * BLOCKSIZE > fsize) - readLen = (int)(fsize - (long)i * BLOCKSIZE); - byte[] byteBuf = new byte[readLen]; - fs.Seek((long)i* BLOCKSIZE, SeekOrigin.Begin); - fs.Read(byteBuf, 0, readLen); - //并行上传BLOCK - BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen); - if (blkRet == null) - { - extra.OnNotifyErr(new PutNotifyErrorEvent(i, readLen, "Make Block Error")); - } - else - { - if (extra.AllowCahce) - { - ResumbalePutHelper.Append (puttedFile, i, blkRet); - } - extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); - } - } - ret = Mkfile(client, key, fs.Length); - } - if (ret.OK) - { - if (Progress != null) - { - Progress(1.0f); - } - if (PutFinished != null) - { - PutFinished(this, ret); - } - } - else - { - if (PutFailure != null) - { - PutFailure(this, ret); - } - } - return ret; - } - - - /// - /// 百分比进度提示 - /// - private void progress() - { - uploadedChunks++; - if (Progress != null) - { - Progress((float)uploadedChunks / chunks); - } - } - - private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int blkSize) - { - int bodyLength; - int chunkSize = extra.chunkSize; - #region Mkblock - if (extra.Progresses[blkIdex] == null) - { - bodyLength = chunkSize < blkSize ? chunkSize : blkSize; - byte[] firstChunk = new byte[bodyLength]; - Array.Copy(body, 0, firstChunk, 0, bodyLength); - uint crc32 = CRC32.CheckSumBytes(firstChunk); - for (int i = 0; i < putSetting.TryTimes; i++) - { - try - { - extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); - } - catch (Exception ee) - { - if (i == (putSetting.TryTimes - 1)) - { - throw ee; - } - System.Threading.Thread.Sleep(1000); - continue; - } - if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) - { - if (i == (putSetting.TryTimes - 1)) - { - return null; - } - System.Threading.Thread.Sleep(1000); - continue; - } - else - { - progress(); - break; - } - } - } - #endregion - - return extra.Progresses[blkIdex]; - } - - - private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) - { - string url = string.Format("{0}/mkblk/{1}", Config.UP_HOST, blkSize); - CallRet callRet = client.CallWithBinary(url, "application/octet-stream", new MemoryStream(firstChunk), firstChunk.Length); - if (callRet.OK) - { - return QiniuJsonHelper.ToObject(callRet.Response); - } - return null; - } - - private CallRet Mkfile(Client client, string key, long fsize) - { - StringBuilder urlBuilder = new StringBuilder(); - urlBuilder.AppendFormat("{0}/mkfile/{1}", Config.UP_HOST, fsize); - if (key != null) - { - urlBuilder.AppendFormat("/key/{0}", Base64URLSafe.ToBase64URLSafe(key)); - } - if (!string.IsNullOrEmpty(extra.MimeType)) - { - urlBuilder.AppendFormat("/mimeType/{0}", Base64URLSafe.ToBase64URLSafe(extra.MimeType)); - } - if (!string.IsNullOrEmpty(extra.CustomMeta)) - { - urlBuilder.AppendFormat("/meta/{0}", Base64URLSafe.ToBase64URLSafe(extra.CustomMeta)); - } - if (extra.CallbackParams != null && extra.CallbackParams.Count > 0) - { - StringBuilder sb = new StringBuilder(); - foreach (string _key in extra.CallbackParams.Keys) - { - sb.AppendFormat("/{0}/{1}", _key, Base64URLSafe.ToBase64URLSafe(extra.CallbackParams[_key])); - } - urlBuilder.Append(sb.ToString()); - } - - int proCount = extra.Progresses.Length; - using (Stream body = new MemoryStream()) - { - for (int i = 0; i < proCount; i++) - { - byte[] bctx = Encoding.ASCII.GetBytes(extra.Progresses[i].ctx); - body.Write(bctx, 0, bctx.Length); - if (i != proCount - 1) - { - body.WriteByte((byte)','); - } - } - body.Seek(0, SeekOrigin.Begin); - return client.CallWithBinary(urlBuilder.ToString(), "text/plain", body, body.Length); - } - } - - private int block_count(long fsize) - { - return (int)((fsize + blockMashk) >> blockBits); - } - } +using Qiniu.Util; + +namespace Qiniu.IO.Resumable +{ + /// + /// 异步并行断点上传类 + /// + public class ResumablePut + { + private const int blockBits = 22; + private const int blockMashk = (1 << blockBits) - 1; + private static int BLOCKSIZE = 4 * 1024 * 1024; + + #region 记录总文件大小,用于计算上传百分比 + + private long fsize; + private float chunks; + private float uploadedChunks = 0; + + #endregion + + /// + /// 上传完成事件 + /// + public event EventHandler PutFinished; + /// + /// 上传Failure事件 + /// + public event EventHandler PutFailure; + /// + /// 进度提示事件 + /// + public event Action Progress; + + Settings putSetting; + + /// + /// 上传设置 + /// + public Settings PutSetting + { + get { return putSetting; } + set { putSetting = value; } + } + + ResumablePutExtra extra; + + /// + /// PutExtra + /// + public ResumablePutExtra Extra + { + get { return extra; } + set { extra = value; } + } + + /// + /// Allow cache put result + /// + public bool AllowCache = true; + + /// + /// 断点续传类 + /// + /// + /// + /// true:允许上传结果在本地保存,这样当网络失去连接而再次重新上传时,对已经上传成功的快不需要再次上传 + public ResumablePut(Settings putSetting, ResumablePutExtra extra,bool allowcache = true) + { + extra.chunkSize = putSetting.ChunkSize; + this.putSetting = putSetting; + this.extra = extra; + this.AllowCache = allowcache; + } + + /// + /// 上传文件 + /// + /// 上传Token + /// key + /// 本地文件名 + public CallRet PutFile(string upToken, string localFile, string key) + { + if (!File.Exists(localFile)) + { + throw new Exception(string.Format("{0} does not exist", localFile)); + } + string puttedFile = string.Empty; + Dictionary puttedBlk = new Dictionary(); + if (this.AllowCache) + { + puttedFile = ResumbalePutHelper.GetPutHistroryFile(localFile); + puttedBlk = ResumbalePutHelper.GetHistory(puttedFile); + } + PutAuthClient client = new PutAuthClient(upToken); + CallRet ret; + using (FileStream fs = File.OpenRead(localFile)) + { + int block_cnt = block_count(fs.Length); + fsize = fs.Length; + chunks = fsize / extra.chunkSize + 1; + extra.Progresses = new BlkputRet[block_cnt]; + //并行上传 + for (int i = 0; i < block_cnt; i++) + { + + if (this.AllowCache && puttedBlk != null && puttedBlk.ContainsKey(i) && puttedBlk[i] != null) + { + Console.WriteLine(string.Format("block{0} has putted", i)); + extra.Progresses[i] = puttedBlk[i]; + continue; + } + int readLen = BLOCKSIZE; + if ((long)(i + 1) * BLOCKSIZE > fsize) + readLen = (int)(fsize - (long)i * BLOCKSIZE); + byte[] byteBuf = new byte[readLen]; + fs.Seek((long)i * BLOCKSIZE, SeekOrigin.Begin); + fs.Read(byteBuf, 0, readLen); + //并行上传BLOCK + BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen); + if (blkRet == null) + { + extra.OnNotifyErr(new PutNotifyErrorEvent(i, readLen, "Make Block Error")); + } + else + { + if (this.AllowCache) + { + ResumbalePutHelper.Append(puttedFile, i, blkRet); + } + extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); + } + } + ret = Mkfile(client, key, fs.Length); + } + if (ret.OK) + { + if (Progress != null) + { + Progress(1.0f); + } + if (PutFinished != null) + { + PutFinished(this, ret); + } + } + else + { + if (PutFailure != null) + { + PutFailure(this, ret); + } + } + return ret; + } + + + /// + /// 百分比进度提示 + /// + private void progress() + { + uploadedChunks++; + if (Progress != null) + { + Progress((float)uploadedChunks / chunks); + } + } + + private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int blkSize) + { + int bodyLength; + int chunkSize = extra.chunkSize; + #region Mkblock + if (extra.Progresses[blkIdex] == null) + { + bodyLength = chunkSize < blkSize ? chunkSize : blkSize; + byte[] firstChunk = new byte[bodyLength]; + Array.Copy(body, 0, firstChunk, 0, bodyLength); + uint crc32 = CRC32.CheckSumBytes(firstChunk); + for (int i = 0; i < putSetting.TryTimes; i++) + { + try + { + extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); + } + catch (Exception ee) + { + if (i == (putSetting.TryTimes - 1)) + { + throw ee; + } + System.Threading.Thread.Sleep(1000); + continue; + } + if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) + { + if (i == (putSetting.TryTimes - 1)) + { + return null; + } + System.Threading.Thread.Sleep(1000); + continue; + } + else + { + progress(); + break; + } + } + } + #endregion + + return extra.Progresses[blkIdex]; + } + + + private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) + { + string url = string.Format("{0}/mkblk/{1}", Config.UP_HOST, blkSize); + CallRet callRet = client.CallWithBinary(url, "application/octet-stream", new MemoryStream(firstChunk), firstChunk.Length); + if (callRet.OK) + { + return QiniuJsonHelper.ToObject(callRet.Response); + } + return null; + } + + private CallRet Mkfile(Client client, string key, long fsize) + { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.AppendFormat("{0}/mkfile/{1}", Config.UP_HOST, fsize); + if (key != null) + { + urlBuilder.AppendFormat("/key/{0}", Base64URLSafe.ToBase64URLSafe(key)); + } + if (!string.IsNullOrEmpty(extra.MimeType)) + { + urlBuilder.AppendFormat("/mimeType/{0}", Base64URLSafe.ToBase64URLSafe(extra.MimeType)); + } + if (!string.IsNullOrEmpty(extra.CustomMeta)) + { + urlBuilder.AppendFormat("/meta/{0}", Base64URLSafe.ToBase64URLSafe(extra.CustomMeta)); + } + if (extra.CallbackParams != null && extra.CallbackParams.Count > 0) + { + StringBuilder sb = new StringBuilder(); + foreach (string _key in extra.CallbackParams.Keys) + { + sb.AppendFormat("/{0}/{1}", _key, Base64URLSafe.ToBase64URLSafe(extra.CallbackParams[_key])); + } + urlBuilder.Append(sb.ToString()); + } + + int proCount = extra.Progresses.Length; + using (Stream body = new MemoryStream()) + { + for (int i = 0; i < proCount; i++) + { + byte[] bctx = Encoding.ASCII.GetBytes(extra.Progresses[i].ctx); + body.Write(bctx, 0, bctx.Length); + if (i != proCount - 1) + { + body.WriteByte((byte)','); + } + } + body.Seek(0, SeekOrigin.Begin); + return client.CallWithBinary(urlBuilder.ToString(), "text/plain", body, body.Length); + } + } + + private int block_count(long fsize) + { + return (int)((fsize + blockMashk) >> blockBits); + } + } } diff --git a/bin/Qiniu.2.0.dll b/bin/Qiniu.2.0.dll index 4202a94683581254b799e41d4a48518312837972..aa4d0d9801f4bdc9b5592e91c5e9873280b6cbcf 100755 GIT binary patch delta 19163 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 diff --git a/bin/Qiniu.4.0.dll b/bin/Qiniu.4.0.dll index aebae508c7e394596e29a1d26e47302e2dda3f28..dc9d02948014f1b2cfe1ea0bca8b936a3b2a6dd9 100755 GIT binary patch delta 19305 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 YVoyzTXz%wv?a1)v@WWrKwSE2n53KvO_W%F@ delta 18727 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%0DlQ!A%ToQ&7vJC2-K zHNA=kge#kThJ?cvf0$A=N6fHy*Cp9+)D^TIF=fhhl5k~Z`3>bWu_mqv&n!oCsQ=8_ zQ-HUW&u;j+?iH;eY3XV;r|*pLr0HlpT`~Q7w4bh%e8Qyg9JIPu?;9sfC~Vlf;;&jm z&7C9khIj5BquJH#hi12`ra~-?PI&F40t;$3q-tFCq^25w+*V`1xc-m!nDsdg!|&gz z1im?P+vPW0*1xpA_omPPR=jYu9oRV3w^lWRX}XaajIOoIH|7tj0KZi+VmwK~coB>) zG7VSIlY*Hd#sI|^oW|iZS~0wu5g%Qr8kt_{*$PE=Xhtx4xZ&N6Z;BiYdyO^8&bCn5IPBerfy&RKwe~##}bWI#K=f@O4upk9fJ^lr=MG5 z>e-6ONR1&iKKia{$|6t+k$}BdhuaBLeoU8GAQt|r5Qep$Y&AH?pOIl?EAm^-CexFx zSXO-WBLjcjA~FKE8@eR&?KQv0P zC|JZ*9JI@}4jQ${@AGKE;^0JNG3d3jHGKR1!BQ*MqeETl8a%R7i-Hp^j~1^7%l#m- zA3@WL|5r+;9=ycwM|y%8eve0i&HiO;pP=*zrusDxkdv~=zVg8(c(?xj2P=U?x3$QY zRgx;J45kH36Fgpj@CwvfnyH&yvAuX(pTJrj5u$6&Y*m=Z*IN6XZT(YaVolRSs^9Mo znm&*2#gO4YJF-2ijTE5wC`rLsP0a!wQGaX zrRbaK_n4-cse8=`bWr$YDaUAeJ*rGExWBQ8w3S*GheiaymE^I4b1*N0(Yu2E&0r~F zp$KNIX;~f}ECZvk*23J0F2ckQRu~>d20gEt?ZMzgqmf{R$s-1tHH*$G7P*Sqoc~4M zY{idQnbJY`2j`f`aHDEAo^tWzy9MT;N0W6q+(A=TwkR_=yHTjXg!ZZ)VUOBT5G!Bi z6<&X=2g_%(y<*2jeRg;~PQ2(2i-&{fHRpCWa*J8$mpKhacl$l6JL^G$Ui1?)e)Z1O zUKJiEj|x^ZRyz0Luv{4+-fX0}BGVr%it~76PdL^=zgvEhJ#uGzvDS|6OimuBg)q?G z5V^JJpwYwjj-9XhQ(xxG0z=1_?d7}DmF$=8?Yq8d@bCV&s+3&Z5dY{|v8vGX{{Wwf BW{>~? From 81ff6ba26ff4c721a1771eb9a8c07ba0ec697f70 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Tue, 25 Feb 2014 14:34:45 +0800 Subject: [PATCH 05/16] fix Resumable put --- CHANGELOG.md | 3 +-- Qiniu/IO/Resumable/ResumablePut.cs | 27 ++------------------------- bin/Qiniu.2.0.dll | Bin 46592 -> 46080 bytes bin/Qiniu.4.0.dll | Bin 46592 -> 46080 bytes 4 files changed, 3 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d156d45f..b7ea0175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,9 @@ ### v6.1.1 -2014-02-25 issue [#41](https://github.com/qiniu/csharp-sdk/pull/41) +2014-02-25 issue [#42](https://github.com/qiniu/csharp-sdk/pull/42) - 简化断点续上传,删除bput逻辑 -- 增加断点续上传中块上传结果本地缓存特性 - 修复bug:>2.5GB文件上传失败 ### v6.1.0 diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 826df04b..266c842f 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -65,23 +65,17 @@ public ResumablePutExtra Extra set { extra = value; } } - /// - /// Allow cache put result - /// - public bool AllowCache = true; - /// /// 断点续传类 /// /// /// /// true:允许上传结果在本地保存,这样当网络失去连接而再次重新上传时,对已经上传成功的快不需要再次上传 - public ResumablePut(Settings putSetting, ResumablePutExtra extra,bool allowcache = true) + public ResumablePut(Settings putSetting, ResumablePutExtra extra) { extra.chunkSize = putSetting.ChunkSize; this.putSetting = putSetting; this.extra = extra; - this.AllowCache = allowcache; } /// @@ -96,13 +90,7 @@ public CallRet PutFile(string upToken, string localFile, string key) { throw new Exception(string.Format("{0} does not exist", localFile)); } - string puttedFile = string.Empty; - Dictionary puttedBlk = new Dictionary(); - if (this.AllowCache) - { - puttedFile = ResumbalePutHelper.GetPutHistroryFile(localFile); - puttedBlk = ResumbalePutHelper.GetHistory(puttedFile); - } + PutAuthClient client = new PutAuthClient(upToken); CallRet ret; using (FileStream fs = File.OpenRead(localFile)) @@ -114,13 +102,6 @@ public CallRet PutFile(string upToken, string localFile, string key) //并行上传 for (int i = 0; i < block_cnt; i++) { - - if (this.AllowCache && puttedBlk != null && puttedBlk.ContainsKey(i) && puttedBlk[i] != null) - { - Console.WriteLine(string.Format("block{0} has putted", i)); - extra.Progresses[i] = puttedBlk[i]; - continue; - } int readLen = BLOCKSIZE; if ((long)(i + 1) * BLOCKSIZE > fsize) readLen = (int)(fsize - (long)i * BLOCKSIZE); @@ -135,10 +116,6 @@ public CallRet PutFile(string upToken, string localFile, string key) } else { - if (this.AllowCache) - { - ResumbalePutHelper.Append(puttedFile, i, blkRet); - } extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); } } diff --git a/bin/Qiniu.2.0.dll b/bin/Qiniu.2.0.dll index aa4d0d9801f4bdc9b5592e91c5e9873280b6cbcf..f977ea633c201c2c58c4089936187c865f58e5e6 100755 GIT binary patch delta 10774 zcmbW7349dg`Nx0n?9A-!?2+9Zn`|x;AS5VaLLh|uNEA>I1XK>WRFD7?2vUwfmIy?U zfZ$+kL{TVsahMVmsG`NHfW!)7QLJL9R?%Xqm{O%!{?B^=(SQ4I`_Jc-XW#F0z0Z5h zJCoTgI;|}_rLA7pa&c$hFsPqKXqjGS0b5C7O6B@PYo5C`Fys($BUdy6LtJYzQ^Y;Y&PK z#eAYTBcvyem?GL!Mrq~cr0W?^R@n^cmrNr|$kkYxL*>Pp))jrYbTW0;#tNC?kWt!) zw>2|lhV+n;(?k`-xkK)*(G1?9R(>C4=a#Y;JeV~%Xe{7eY<-LXbqq8P* z$5QSHUTqxZ@bv0&@#00zG}K_vk=2Wj{glV*!k5k}4Nxr~xl4af7H4yZ^c3pOrWz_J zX_pw;A8%{!(kae~4(V6ZC-;Cm&MM^Q5X~~sCzUTC(2jm{7%-fE{Z3YXcUI!ukw1h@ zb?WnnvuTdiu`OHbbm-WQ+T%Lj+2VZ~VZ|)UZ&Y`oImmKK1$Nv4Z z>>v4*PA8u>dKW(ZFw2U_s^=V~CLg=qM$KP&4@#PoM4GPY((x8&W~ca$Kl17RQ=gfX zOwFpW$+XU%PMK_m^ZQQS(w35gr98S(v{l-Rx{%#Zck&BH#m^*ezA)}b%NIKv3W@__ z1Gvo62sxBJ;(S~1h<6(wSsA6NsCFLi+$sD9aq>zJO+;2$=r?91lBuzCD^}*{g$?E( zc|f&utT4~KD4YH+cbbV_q5WBxo@N)>{8g7xi6g0*6XczZ24=W&@)=B5=`82!t{+72 zCL850n<+k%%F4xOq--hwTvSaJT~(p+b)>BjUicufmXWb|_t!Z-O0sYjx0gZF%7vwz zvr9K}{M^V@S0OH!A%^Ci7BxgG!j-nzE+)6t-`DLPmUu6vw<}hYNn9^pz~v5Ctai*E z*?D5JxT}sRrJ+d=6g9R-|3UH^)4S1y4wN}Gm|0=!Wd2p{Gq4C) z#QVBZTN_#1nr5}p?r|;T3fj}op&ofoV{5nL>bc6DE@#78-LoxEerb5Uows|YI-y>X zHjg#S(vp&JzS0$qjZeel&X8VNIgiWymvYc7bK4Wm5{NRMaE`PNJ1csHxx$!lEaeB3KpJL7e}@0H3zPPlh^HWfw}LMIxpSap68^Pa*z)&B28c3#5h-bKFK zsBM+L&o7$U&U3x9qauAp8U-(WQkF+Yr;dd**1obn?$N~}M!a2kH~*ydU&pHwrEBF+ zQah(TZ2_;lv?YC%{*1D9<(mLnqNqRK{+g&CG3OU5CAnO8qxoyJ{au4ZkyltPdO$5Ca)W(BuA94+J=A^$A&DKXsIM#!Ntd|xPyElNZg=9fKj>I5O@i56)tP9o!ZG0HyQB6XBG5EDFfc+sJ)kHE3Gd4EX#;kZA zH8Jf6%CJDlS|N7}c|^#s(tb!Mvysl7GSWMy+ZZO~1fi)&KUKf)`W9MrF}??*wJX$S zGK1ZZ^I){nMMObVD;lVM%(Ac&9#%=(p@LQ;NMS*Y({9nSum*90CJTB58G>dI1yPGE z5jS7NZ9tx&2P6$gzCcGAJBq+9+G7;B0i6W>ii*i1>MUr#pp7ULbd1P@P3R)%E21Da z*Vhk-a}Cz%mrvqL;eicdv=i= zNbN9&dYE(O#_S%qQ$B_}Jul(rMKe5%Y1rNyj}0>3QVk%XG7$;XOf>sEi$9=+HAkKUKJ& z$Uv^5Y9bRe6xGH~HQeamT6kK&jZ*g>+@bJ8>fVE?lBmN1MjJ}do7fz?*zjWOW!qbZ z9}R*k!IK71m&KDx&mewI_adMMpT~AGVzFD%w%8AiID90i$~qexZ9+WGDLhZz(<2Z) zu=2Uk;_CDSBrEd9oi-BCN|Kn1FyeEh=TvVSGmJt>WNTq2;xR#$7#~-_lCV|Ko4C*0 zgb4m3s0LHw@}g!0OWN`@HP{!s%Sgrtf~u_PaUEC+&MI0MS7@f-f}-lUCZr`PVW#B1A zeJ%Zq37L3HkvG18W#XtLF;6Y=ktAA*q4c*z)77%G_gZYa1AlhJwB3@`V)+^$LW+VEvL{VuD z>LiIubFi7;T2V!|QD$4bEa**PYme${WZ6Thm}~L0qH$ErwKy(`;s%+yuw)$Lqwk0e zK{enTu@j1;0@ox>i@((@!1`-1bvT8nL6GdQCpywCk+1gL_&H`TOjERss5drB5`*Z2 zt%BBIUHodZ50-QgadGCSV?KWpq$_q`{O`;g@v<;3!5i_7=3smz zs0K&l^R*$cI&#k%{2{)RF$6h+*5F+H=jP3@3b>7v$9)SO-O^J}$aRlEZ+cwiaeBgV z_h=07%1I7)EXH>gPoh;;AYqn!EanSil@&=?O0+~#>x4Re9M&sppK#h3hi4QOCOqgK zkJl7kmrzU8plE196DHtuMdK0**aV!BBX$n_2+69SdiY;wH=tp!zC z6=b^;J(aDBYx#BfF(vp!5_SJ;cL_c1$PRZU>~~K?p`zD_?!gR2hZ7pz)A5X= z6GWvrAt=gs_d(3S=hBEX3E#VCfb|qf@m<12_e`V;qBRT~Rv8Kv#SqOxqoQ5DZq~i% zPJdPK)lLm}GUlLKQG24fs8iIPXdd1ZR28)bhwJqDI3v*-6FzOs#|1@G$yScU-l7<5 zF4@YFDT&G+Y%M_d%XAPGC>F%e{9CLFSbcb04VH$(tP<@6RatAoO<0V6ilXbn1#B^f zE8I-RCEza;_!_=Iwk24g=nb+h#UqN2k!>k9Df)tJRd`j=U&&U521TyKCftuN6vZYM z&{Iv5qRc26mm!A!AmAOgC*v}tD(XhI<>;)aAK8|pSkbV=66*nsS2UhHA3(XHY2^6; zmMNN>Sf{VRFBILMc-mNjIz=^!(K@{vhZJrmV>Lcdw3Cvq#J7rGqogZ=B3bC+#EIG} zq$v6%v4ki`(Vr>qK@=%6lM2{_7@{aWsR^qwRZ(tIL6oh=Y>Bj@v#mAQBnf?!$}I=a z6!Q+{jdLwt7gS~OyTe+X5L9XLyTe+XQZ{~fco^DsJg(B>cZY}J6I5mKJ3tNEC>y^6 zL~D?%jQy#$M{t8O-bQslg5lCerL{1Bj@{BGuJl?Axt@0+A21%p3`N^wYpiuxE2zqv zL^&TrouZ+BP7R7?a$6Lq6wVW_RzIGUUzC~bF?733o2>O1dYQIbPh!$#+G%aV0!h{? z%JMWGQ&cPHWkHqLoV3+?8XsPcJBTfaex_V^CQa0~;G&{el1hkt{Y5d>0kUmHwxajQ zwiO)}@iA?~U`35IYuj+UB7UxJ#~elcT-}Z(icV2!&*O=x!fz<>d2Ch0cYYoAE8;u9 z4(}=AXW%b!M$vhS`z5}YM6-4fJD?AcW%KTLAYG6=)^{LB+4RUntsZ>`M7e9F6^N7& z4pc@y-kq4F0{M7%VurHu+sX@gK-u_hNTc==+GTTFl{MZMWiR7;K})RoxO2wK z7@};g;w~6_F-6((;!JZd?p3y4^yK#nRw>&+dh&Y(KPRH`S6L(JQS(*ok*-u}(0mn# zFH@qq4_{oS7Upj-u%#$QO!w;;F6d3hAJAXN2x+6|n-#{J&|3*l?1)`&>_?Lz`Jj6U z8~Fg`{qG481fI30^+2=K@0jCr#BYGPdgG3kBO_A5E-(rNK zF+}fRwW89<3F|NpC|W>t1h|REMXRjpNR#z0QUq36>mvUk%2D)OME4v;k)oZE0MQ^x zH2QeYdsrZe9=+nUr7qu5aA z@Q`wS)cy|VP^V~E@-_DNXpn&zncRt}`$(R&26rZ3XP?IcMN^V*u`l8oMRSwyu)*4m zlAh;-vu(x}DO#EwU1GbKcQiN3={8xCpel=>h$hQd#7{(%^;X1B2saz8h@TK{Hdzrr z5iPb@5kCpi1j? zN)uq!%62rlPLE+vEBZM3v=PG&DEflpg6va8XDKeo{-TJN7GmBpqHK$o7K*Y2iPU`o zi)Fcz@I&$ob{tC@D_k*vE~hZdRb-{q*kRTns0RL&i7d>%Qt-MX&NL-dOgOtZaU-L|Eo$z=wCwhfVs^+f$cUyMwZ+x8N<60G6^5jKd z)Pq3{mJtlP@IAG4T+pu+Dm}-NRl_Sj?lYU(I`%ug#;5TwS$pA-#zNG`a=yf)X| z)T>e9Bn<-s-0-R}NDVLUl7x3-e58)P!*KU(NS-q5~-}h_*rB6foqI)X;u4;rU<;Z*O$-b w-Ka<>_t2%V|8!*kiN8gi$u2ML?;l4+uXNUYqU6qy@*Ua@ za!)Xv5bYc3%L0aMk{a?zx==_`N0HD=f2o(6f8|M~&=vb%Tp~ZN{hyaU*5LZ-qLeZr z|98}E(re%sXp}+1BH=3Mp!pGSWhOM-M?Nlbi0D`){Qui)T$Xad;@ykus~6-2CNCtp z5B?~s<7br%r>U)r9m^o~z7W^*J+TLQ>HgAPyqg?nWA>G*aJNXrz=r1B9k| z`zE20`ca}?(o8dl+8VuQ=iSc}`lygg_=kpNBwgT6x^Oa-lRS&%6}(D#@=e5WrR~BK zr2qf#gJyeJ&hJujaxL}nt^XoP7q*KIe$%WQxk03Vb}a9{oshXCH58C^p_|a`^$Y<2 zQ>ZOI@w|}^NySw?$1un>6`u#TAO zEuswfdT(F@#H;UT;dlqr-)qrVyu<0^uy-Pv8@)RAh=5we`0k~2VP658iA<7|+Bcu= z1OKzgH{5MddLOVmN#7ffmQ0s4_Mc8KlHCiTn z&!4aH(RbGJSW=*e)`b=Ni?p`vdj9~eEph{cv^*N|P}1;hmFO9`jq(%)4q^b~^Kmnq z5@@3KeSzpWtrjZ+1?03YFp=6%1xiTn4lE(fL23`j9|DWD2^4mazMtSlqzV~gftdB$ z?P5$5kP)+uzF@j0W~X)%*Tn20eK+qbqQp0~5G#&p&?-fS5Ow*kCU$_foZaVbjB0Dx z;+TA`mOUBs7n0A!oFlnAW+DZ@7IQ&+mcp28kEnVdYZ1KY+Q$Y5`|JDIZNWzJnG_tP z^R*nNA7O6#+A(ixS1Yf0=R`_dwlD9 zz}p^wcRftfrEezb)wht06YUiJ9cs4{?W={%*S{c5H%kxs+M`HMukSbI2j>5qzQ``8 zN9N_W*X434q2&Iu{FlJ z$C_zXTGiHL)=Spg))&_ImdBIj>F>G2Gsp9|XP4)I=eXxfk7eiC-RvRuX!~w^p}o?6 zGS+^@K4^bne`0@S|IIeMsor)@=5!}IG$o%Njc!lrOmdQFPZzQ*r8{Znr1U1aAmw_J z_Y3_RA!~(PFMOU7ve4#vwu$x*A$JQYeWdkOp*fIp19`q9+P{mY3?n#f^57F9=`lBN ze=5vh33)bU#7{Kmgy#ieHB)(^F{wN%LC8!Y+Y4DJWRZ{qg&dwbmORIZ_QcdE51t`X zlnd3;)H_JCTC_I_*?cr|96N-5uaK_`c|gbpAwL%KGa*llY-fd(o^p`qg_R15QfG2B z(r~d^fSeU0jgKslHi_gW*Hn@bp=p`M7bPog2FcvC*(CpMXXH~LVtb^`r*;vw6X{(` z8lQvV!XVA(QkK;3pOK|!MGSor{|}tzKcmz5E$zxr4<|G`?#3Rz$I`h@r~hia^mDy$ zJ0_%PF1RB6gkL8DG+GoY5J%^xM~{-#9zQQ~z?s0eAhn zsz!hP!nHd+^&{6m?Fx2}?fOK)oFO+=*$?*Sv4IUJs5~??P((CT6!Vo9zRD~gSd^#D<9CV7r`WSvGsd`G|E(-bEew&uIFuKtt+mVAfoKIZy2v&|0co z*2TX9P{ZD^p0uH^$$30|Mk05t>O(P`Gn1<)X{g$q8C7eWTDxZSi3xqJbmRHz>L^G_ ztXu9}k=rAzXm!hpdy$ZmtKnwFxiz=PnEEupvKEz+^(nPHU|@*%Rda5lX<2&CLOS^1 zS>&gqU(K0HfpIF7uv$5anmIp`J5D2X4&+{Fhqcw&G>5ukN)Urh+ zw_&|<4s{+lR6+%Zz67ZLy@{%@zABYwmeZdP5GAA3-bx8;i^+s_-kW#WT=+V5s9#FX zIPxV0Q8`ag z$wR40`U;G+(!oovOsalZ9Fwbe@MFVjs-RcBl0#?0f)c4) zL#(8yFW>!Dj-NrVyPNCPP?TDs)N=NyT26qA+|>(lxeR<$(1{4sa&o78%5|=_{$bFK zERil-%c@^XlGyn^z~hb7uXQFCW#@^-;h`#QN<)hphNtpxdqn2?3yb-wpzqIKh;_OSi8$Jjs56R={fETH zuJ2ST?F3KVdWQ{(bLJ1RvVPY|>P8CZU#3d+^QmrfHV(v+U5TE$joeT3iOcoi13C`lIqPf4Tb<}fmB+o&g!sZ~?#`6EdmyP= zC-vOM6>?9#dIITcXPpYAtdSvdXIGHUYu`Gw#BWpEsC|{j*i3KNk8Be7sr?K>Xq6Dh2?=ceP~1Yyp`SPPJ{_QR=ss%7m=SdBAfE5Em0T32(lMCPBbWZ) zLG4_}9MPX0bcT-TXV;j=JQhAQcar_t^jH?sEpCgfogN)m3VXFxPwEP59r-s2dw~2F z-nG8Bbfoy|DY7qF3oX8#o*;Jk_V_G(>ofd12Kl*q1z8JA{XD~ZVR!m@hG%U5HqFAH z1bpfL$#0=&;Fu={g)}J(w+48JCjvb5En&Y1{20(-1s~P#M{oWZz=$AMrw4iD^}^mN z>}lc8is5RWu+wAs#AXY-On6qt*u2|j0dJEH;&{v+Ul2bD>ksjHbPMqm50Z_=qoKVa z3ui*SS0v2+8R4J&L3|$Oy&|!Dd=cct=EqvNC!VV-(hQo?CSmsq`@XQ>3+wMg~~#vvD@)87@g@7q7YU~8mD~7GI1A7 z)=1uog4QBL-9nhDOi?oNZ-^5#N6>w=8@N_Q6v75%ihfH)zs<-Kbcaim(NCZw#eC86 z31uU7+>HK${+)`+BpM*-prD6QDClh>6OUk^pp!%)JlcA8bev~WI^C6$OqFb^u$ktQ z)V{!63SIw3VYs59ulY3D0m2puJB(}?qs{K*A4l;F6U^txUP<=UJ|{fSo9X1=FFd@Lj#q{K%uAOe>U5r`PCtOsbh>cRY%GcG zAkREWD`E?1QnyIDCstz$oOJO-X-+zBw$Y2nK362VN>gw|P$M3Wou#QzGeAGhc#KFx zuB4qrI;te?ja{U9F}jC{G)~d*CT2@IL&KYx=Ms%jz$`2yqI=LQI2e1U=EL^$;+t9k z?SdM?lLoOXlP7f}L%1)CQwxl^!CEYKOF9($-&!0#5Y%kM$8{hcKS)ZAD`0g0r`KG* zGCksUs|kp5vI#GY>(CO=-4(@JL=aCepgi;@Umrb!LYGL())TQ&P$O=oq)FH==oPH? zbs!n11hrsQ+(11UO+9&*7JMB0q87!wf|`vraeY||z7u3O8xO=4>nS)R#hp}lDkA*J zN5k)mxfW! z?nsg}mb4z|E6JWrVhqgS|(;m;~i9&Pm2!GsyHok4n)_Y=~z*mIW2dgf0>#m_vGaRE8j*o|pV=Z-}?`p_nh}aiU^u zc1g@)7`6*qi|6C-(}$r+eEMoeTl{nS2!#5HEO;aSkUkpul0J_AP`?!W1U2Ea_!Ii& z_&`t#{u1BMR!U*y^NuZ069#Lg$Pu&_NeN%;6JQi@jZ@e=h3@NaWL83*H6{<@n?xo1t=pnTSNxRm@ z5GigW@mh>_MM{&cUx)3kCa&~yB+-W;ewubs-Pa>u(q2KOk`5-cdauVkmnh4NM5{XW ztH8ES{VHG|ka&oyslcDlcYM`bL9asYfbS(7^3F%0q~k<4qDs4H5&^fyVa%mMv@)r(3awiq}8O=BC*(ZXSjjHT4WRpqPnj% zmZ9i8wV@s(1o3NzpNn3+?k|vV228&&y6Iy4i#TJ)vUD9&H!L|{6JllP6 zuEPO=%?5uwtiwlw8V&w*Scel*<4=cspj^T`HX8ita1Z=~nhpL0plvKQ{sd@2uGHpI zY4>8R)Rs_b_hPcE*;HG$ejj$bqPWu6qjV%6!hONmfGSCcVmBH0W1XO8<915A5xXQ! z4{&OiiCrfU;cNs&KRevdn($R8`e$2zGEqB%W_ol+Y`r9F$?t|oTSbI2LXOLN}}cjJVh z7EDeatnES3rCe*l)kOb}sgfoqA64wV=$*~QW@Db;X8SNwP?J#*_rKacluGTAI8}ch zbEP&ZE=W`(wK971djWSzZ2`Ucy@30qR!gs%FJg~NRA`d^A`YLYuKIo(pPk2S{bh{n zCW;ZueE^dMy~6kl`T#So9=&MvzVd#xuPB0<$UKQ z&(Pa3dK~ZPz9+Q9-X)N~`@Ckf_wDbhW=G&oMtj{3Mq=(R%Y3is-e8_p_o8n8z_)kURTN zP%*`Q{)y%O1Pg`8m+ejM6D*S*r-iqepJJb+Nc36r1d^`cNt+Rk?l(`ONK)76o8}jo zB`GWVvH2w$B&CKwHowAyf*Nr_^jq_56kjQxe~l=Ns@5rBs$1zLQAhg@MS_}fX*6hk zk0wb|q8C~n*e+=%(O+;xQbn}D`T?f}xikC`Syzcd#RPxENSE-4^%H)?bwvF6hsDvM z*3W1V;#$;3M-iP8)PmchS6Y8X?lhi;K2}9{q!F?Li^YIudEu>7mt$gR;9 zOJy$#a*Oe@c0tVszax6tXPo%+kKYo#tV4?Y7GbcMYj~PwgWnMimMV$g5luEg62Bvw zY=k6!OS0HZN&JpzvH6nt9nr^DNaA-yA6qAgKL7DsqMtn}MgA_}XM0={%NAex9r!W`-s9Wi7YWJRch~0mKatbsL?h)r8F_DSc-p% z?p8zWYDs6K9a@MjlVqlJAk6NS6rWPS!fcBqURo@BQ4%jLmbJM=!xykP#=rFAC%bFP zK`WlM&v40}N0(C~J1((T$~G&JHO%B<3oc42XNhdPq(Lc@SrU6yQc21WRx&#!XaiHQrRpQjYA1xUn;9TCz@$Qcb=ys`RtQrdGFv#P@X=)odqy93b&ZF=}QNX9g*PzMB4({}!8Ee=qc|PNDAF>?RKb_bb>hdc7uMT>s=C_j8X2u7^+ToQKD|XW*RY z7{&9|?dcx=nU$x;Sv{+#JoTMt?6&DkWlHB-uV{ya9YR*YrDQ#D^SEkfdoCN_LhtGP z416p$!-g2%-t6UP!`)gRP7~?e9doYRKP&zJ5#!ulmUzKGivR8ItajcgOSG?`UkNbu zC99x_tOq4zRa_?ghiDs|^ShpZ6#0+F{TF`wH&;UELT6~axFw>LI$?jCu7Ugt+)K@E z-zg&9Je@D)U#=4ct0~4qcLSTxb-n2D53knWl-Rk5GX@{tYw}ZkROE3l7k;65#AU?j zm-sw}-+DX8$*^^BU1@4XrZWImB8Y76W|JX&85#xGBcO@(h;=JCUq{sboEv zEMw_31zT-W7!z-P4;8hn?#{o*ta4T+Fh=Q#i-Y5pJeu)D^6+ep7!$mb@>~{d z!x+ZbV**3czx_=*x{m&dd#jUq#shI~^IJ3v{< zR{M_H%35|;Oh08kdm`o(+18jJ$i5s?PMu$mIioyA-I!;OsCqx^6*}wL&!&Y&tNYpP z&{2w67#gqgb2&+UgB=b{Q?J1np*phsd^h69&~mjmm3t?BBhO1e#!|y;)z4W@c$3Qa z*;}wb$H4GoDz{Imd2D2Ox7rh>;qjEZ#5$>#(W>lL8}UrITnXd7a0jjfkNH;2=39o? zo*Lghx%BI%p|OKCzTMhrBTw@U*D7#BES*Y)FL<)B8N&7yHc!}r>EbX<*fC^_^$DVV zm9S;XaVK%kJ9ZBxoBpUPhnCVnZ{=~axyqCD`=&zWXVt_Qhol~i}nTTF>3b{?Tdvi396^b zb*b9j-v^V_+}6bv|HA@j)ds7U-j`QeK9A3_=iQdv81i}csSlC;Pjx@px71@~KT;oZ z(&j&8mui!>>$L@1t+qjXN;{~%tDVqJX{R+)kJt0{OZ0L2e0`<T%y<5F|yzhCx^ClZTjB!S}vDjE*tTfgcTa1^DKN{Z{jQ%XDk2%e(F;|*Tnr-I$ z<`?E)&8Sskjkji7H(E=qyR8STr(>%22kxqaKqt(MA%_X``JI`?lpNg}d~P;-RM6P^LWmIzxa>@;D^ zg{(&; zG(L@B8qXFltQ+Z0GF7NlkWI2X8&}Ba)WKbqY!RB9b_+#r@zjyMSa?RH@slzt?N+iA z(^ioEmxEEvRMB^4+A3<7Q#+CV;3JK%!A(MN<)qY>*1uF{s&HJfd#vgLO z{9I0dF~RBAz8AW1pGto>dG2Sbe-91w>$o!iUV4%FTVFmsI>nEQa^;WC?`pcnKdcVG zxAZ?n8-POkKbG>g{-Gwuw1&-}UwLy$*|l@ZTR*64^G3=zU&|RKl?!UhDi$odw0ueH zmfMa6T9-S|npxSiF&~w<7V}VxT>8tNbj+bg<{~;)VKHjxUpcO89q_xyJfWV?dtQoM zbYSHDw-kJssiz)kJ@sI%YA~jyGbIkK^B!5Rb}`aDEOu7xRD~L`4Xc8|U>C11m=GIK zjM#>atx1m;c!Jy7<&5a?Lc23#M^xF>?kwH0&PjjzaBFbq&mQG)QET|=Z`j&g@Baa1 CXhK#1 diff --git a/bin/Qiniu.4.0.dll b/bin/Qiniu.4.0.dll index dc9d02948014f1b2cfe1ea0bca8b936a3b2a6dd9..3cf06f3f2c23cf987651de0a8621469713c8e337 100755 GIT binary patch delta 10774 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 DPO~4B delta 10969 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 Date: Tue, 25 Feb 2014 14:42:08 +0800 Subject: [PATCH 06/16] fix resumble put --- Qiniu/IO/Resumable/ResumablePut.cs | 1 - Qiniu/IO/Resumable/ResumablePutHelper.cs | 87 ------------------------ Qiniu/Qiniu.2.0.csproj | 4 +- Qiniu/Qiniu.4.0.csproj | 3 +- 4 files changed, 2 insertions(+), 93 deletions(-) delete mode 100644 Qiniu/IO/Resumable/ResumablePutHelper.cs diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 266c842f..3ffca2d8 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -70,7 +70,6 @@ public ResumablePutExtra Extra /// /// /// - /// true:允许上传结果在本地保存,这样当网络失去连接而再次重新上传时,对已经上传成功的快不需要再次上传 public ResumablePut(Settings putSetting, ResumablePutExtra extra) { extra.chunkSize = putSetting.ChunkSize; diff --git a/Qiniu/IO/Resumable/ResumablePutHelper.cs b/Qiniu/IO/Resumable/ResumablePutHelper.cs deleted file mode 100644 index 20e2d5a9..00000000 --- a/Qiniu/IO/Resumable/ResumablePutHelper.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.IO; -using System.IO.Compression; -using Qiniu.IO.Resumable; -namespace Qiniu -{ - public static class ResumbalePutHelper - { - public static Dictionary GetHistory(string filename) - { - return ParseHistory(filename); - } - - /// - /// File Format: - /// i,offset,ctx/n - /// i,offset,ctx/n - /// - /// - public static Dictionary ParseHistory(string tempFile) - { - if (!File.Exists(tempFile)) - { - return null; - } - string[] lines = File.ReadAllLines(tempFile); - Dictionary result = new Dictionary(); - foreach (string line in lines) - { - string[] fields = line.Split(','); - BlkputRet ret = new BlkputRet(); - ret.offset = ulong.Parse(fields[1]); - ret.ctx = fields[2]; - int idx = int.Parse(fields[0]); - result.Add(idx, ret); - } - return result; - } - - /// - /// - /// - /// - /// - /// - public static void Append(string tempFileName, int idx, BlkputRet ret) - { - string content = idx + "," + ret.offset + "," + ret.ctx + "\n"; - File.AppendAllText(tempFileName, content); - } - - /// - /// ȡļSHA1ֵ - /// - /// - /// base64sha1ֵ - public static string GetFileBase64Sha1(string filename) - { - SHA1 sha1 = new SHA1CryptoServiceProvider(); - using (Stream reader = System.IO.File.OpenRead(filename)) - { - byte[] result = sha1.ComputeHash(reader); - return BitConverter.ToString(result); - } - } - - /// - /// ȡʱļ - /// - /// - /// - public static string GetTempleFile(string filename) - { - string tempPath = Path.GetTempPath(); - return tempPath + filename; - } - - public static string GetPutHistroryFile(string filename) { - - string f = GetFileBase64Sha1(filename); - return GetTempleFile(f); - } - } -} - diff --git a/Qiniu/Qiniu.2.0.csproj b/Qiniu/Qiniu.2.0.csproj index b5e9df3e..f38ad126 100644 --- a/Qiniu/Qiniu.2.0.csproj +++ b/Qiniu/Qiniu.2.0.csproj @@ -15,7 +15,6 @@ - AnyCPU true full false @@ -53,7 +52,6 @@ - @@ -102,4 +100,4 @@ - \ No newline at end of file + diff --git a/Qiniu/Qiniu.4.0.csproj b/Qiniu/Qiniu.4.0.csproj index 43ffa972..0535cc75 100644 --- a/Qiniu/Qiniu.4.0.csproj +++ b/Qiniu/Qiniu.4.0.csproj @@ -53,7 +53,6 @@ - @@ -103,4 +102,4 @@ - \ No newline at end of file + From e557dedbbd03824a940932b85892a5f8e62b0ed2 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Tue, 25 Feb 2014 14:43:57 +0800 Subject: [PATCH 07/16] fix resumble upload --- bin/Qiniu.2.0.dll | Bin 46080 -> 45056 bytes bin/Qiniu.4.0.dll | Bin 46080 -> 45056 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/Qiniu.2.0.dll b/bin/Qiniu.2.0.dll index f977ea633c201c2c58c4089936187c865f58e5e6..92cd6bae24959261ee944a6216de24cea445fdaa 100755 GIT binary patch delta 16616 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 diff --git a/bin/Qiniu.4.0.dll b/bin/Qiniu.4.0.dll index 3cf06f3f2c23cf987651de0a8621469713c8e337..a0595c76b72f508c7a25d3f0dc77f6a206a0550b 100755 GIT binary patch delta 16616 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 C9WyKd delta 17596 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 From 924818bf1284018cb7cdc0d5d2351e07ae22eadf Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Tue, 25 Feb 2014 15:27:18 +0800 Subject: [PATCH 08/16] fix --- Qiniu/IO/Resumable/ResumablePut.cs | 18 ++++++++---------- Qiniu/Util/CRC32.cs | 4 ++-- csharp-sdk.2.0.sln | 12 ++++++++++++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 3ffca2d8..7821a2a2 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -98,13 +98,13 @@ public CallRet PutFile(string upToken, string localFile, string key) fsize = fs.Length; chunks = fsize / extra.chunkSize + 1; extra.Progresses = new BlkputRet[block_cnt]; - //并行上传 + //并行上传 + byte[] byteBuf = new byte[BLOCKSIZE]; + int readLen = BLOCKSIZE; for (int i = 0; i < block_cnt; i++) { - int readLen = BLOCKSIZE; if ((long)(i + 1) * BLOCKSIZE > fsize) readLen = (int)(fsize - (long)i * BLOCKSIZE); - byte[] byteBuf = new byte[readLen]; fs.Seek((long)i * BLOCKSIZE, SeekOrigin.Begin); fs.Read(byteBuf, 0, readLen); //并行上传BLOCK @@ -161,15 +161,12 @@ private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int #region Mkblock if (extra.Progresses[blkIdex] == null) { - bodyLength = chunkSize < blkSize ? chunkSize : blkSize; - byte[] firstChunk = new byte[bodyLength]; - Array.Copy(body, 0, firstChunk, 0, bodyLength); - uint crc32 = CRC32.CheckSumBytes(firstChunk); + uint crc32 = CRC32.CheckSumBytes(body,blkSize); for (int i = 0; i < putSetting.TryTimes; i++) { try { - extra.Progresses[blkIdex] = Mkblock(client, firstChunk, body.Length); + extra.Progresses[blkIdex] = Mkblock(client, body, blkSize); } catch (Exception ee) { @@ -202,10 +199,11 @@ private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int } - private BlkputRet Mkblock(Client client, byte[] firstChunk, long blkSize) + private BlkputRet Mkblock(Client client, byte[] firstChunk, int blkSize) { string url = string.Format("{0}/mkblk/{1}", Config.UP_HOST, blkSize); - CallRet callRet = client.CallWithBinary(url, "application/octet-stream", new MemoryStream(firstChunk), firstChunk.Length); + + CallRet callRet = client.CallWithBinary(url, "application/octet-stream",new MemoryStream(firstChunk, 0, blkSize),blkSize); if (callRet.OK) { return QiniuJsonHelper.ToObject(callRet.Response); diff --git a/Qiniu/Util/CRC32.cs b/Qiniu/Util/CRC32.cs index 01ea3786..e8c638a9 100644 --- a/Qiniu/Util/CRC32.cs +++ b/Qiniu/Util/CRC32.cs @@ -50,10 +50,10 @@ public static UInt32 Update (UInt32 crc, UInt32[] table, byte[] p, int offset, i return ~crc; } - public static UInt32 CheckSumBytes (byte[] data) + public static UInt32 CheckSumBytes (byte[] data,int length) { CRC32 crc = new CRC32 (); - crc.Write (data, 0, data.Length); + crc.Write (data, 0, length); return crc.Sum32 (); } diff --git a/csharp-sdk.2.0.sln b/csharp-sdk.2.0.sln index d3f062ea..3a6a6cd5 100644 --- a/csharp-sdk.2.0.sln +++ b/csharp-sdk.2.0.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.2.0", "Qiniu\Qiniu.2. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.2.0.Test", "Qiniu.Test\Qiniu.2.0.Test.csproj", "{95DC2A77-2344-4315-9F6F-334CC928459C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.Demo", "Demo\Qiniu.Demo\Qiniu.Demo.csproj", "{6684C419-1723-4792-A567-7F1D821B6DFA}" +EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = csharp-sdk.vsmdi @@ -42,6 +44,16 @@ Global {95DC2A77-2344-4315-9F6F-334CC928459C}.Release|Mixed Platforms.Build.0 = Release|Any CPU {95DC2A77-2344-4315-9F6F-334CC928459C}.Release|x86.ActiveCfg = Release|Any CPU {95DC2A77-2344-4315-9F6F-334CC928459C}.Release|x86.Build.0 = Release|Any CPU + {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|Any CPU.ActiveCfg = Debug|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|x86.ActiveCfg = Debug|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|x86.Build.0 = Debug|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|Any CPU.ActiveCfg = Release|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|Mixed Platforms.Build.0 = Release|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|x86.ActiveCfg = Release|x86 + {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 87df4a3e6c14462725c6cd1df2b8a8092e8abba5 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Tue, 25 Feb 2014 16:24:23 +0800 Subject: [PATCH 09/16] fix --- Docs/README.md | 24 ------ Qiniu.Test/IO/Resumable/ResumablePutTest.cs | 8 -- Qiniu/IO/Resumable/ResumablePut.cs | 93 ++++++--------------- Qiniu/IO/Resumable/Settings.cs | 11 ++- 4 files changed, 32 insertions(+), 104 deletions(-) diff --git a/Docs/README.md b/Docs/README.md index a8944883..de9e53cb 100644 --- a/Docs/README.md +++ b/Docs/README.md @@ -426,16 +426,6 @@ public static void PutFile(string bucket, string key, string fname) string upToken = policy.Token(); PutExtra extra = new PutExtra(); IOClient client = new IOClient(); - client.PutFinished += new EventHandler((o, ret) => { - if (ret.OK) - { - Console.WriteLine("Hash: " + ret.Hash); - } - else - { - Console.WriteLine("Failed to PutFile"); - } - }); client.PutFile(upToken, key, fname, extra); } ``` @@ -457,20 +447,6 @@ public static void ResumablePutFile(string bucket, string key, string fname) ResumablePutExtra extra = new ResumablePutExtra(); extra.Bucket = bucket; ResumablePut client = new ResumablePut(setting, extra); - client.Progress += new Action((p) => { - Console.WriteLine("当前进度:{0}%", p * 100); - - }); - client.PutFinished += new EventHandler((o, ret) => { - if (ret.OK) - { - Console.WriteLine("上传成功:{0}",ret.Response); - } - else - { - Console.WriteLine("上传失败:{0}", ret.Response); - } - }); client.PutFile(upToken, fname, Guid.NewGuid().ToString()); } ``` diff --git a/Qiniu.Test/IO/Resumable/ResumablePutTest.cs b/Qiniu.Test/IO/Resumable/ResumablePutTest.cs index 2de68ba1..7a472060 100644 --- a/Qiniu.Test/IO/Resumable/ResumablePutTest.cs +++ b/Qiniu.Test/IO/Resumable/ResumablePutTest.cs @@ -34,7 +34,6 @@ public void ResumablePutFileTest() ResumablePut target = new ResumablePut(putSetting, extra); // TODO: 初始化为适当的值 Console.WriteLine ("extra.Bucket:"+Bucket); string upToken = new PutPolicy(Bucket).Token(new Qiniu.Auth.digest.Mac()); - target.Progress += new Action(target_Progress); TmpFIle file=new TmpFIle(1024*1024*4); target.PutFinished += new EventHandler ((o,e) => { file.Del (); @@ -63,12 +62,5 @@ void extra_Notify(object sender, PutNotifyEvent e) PrintLn(e.BlkSize.ToString()); PrintLn(e.Ret.offset.ToString()); } - void target_Progress(float obj) - { - if (obj > 0.999999) - { - PrintLn((obj * 100).ToString() + "%"); - } - } } } diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 7821a2a2..8e854f5a 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -22,14 +22,6 @@ public class ResumablePut private const int blockMashk = (1 << blockBits) - 1; private static int BLOCKSIZE = 4 * 1024 * 1024; - #region 记录总文件大小,用于计算上传百分比 - - private long fsize; - private float chunks; - private float uploadedChunks = 0; - - #endregion - /// /// 上传完成事件 /// @@ -38,10 +30,6 @@ public class ResumablePut /// 上传Failure事件 /// public event EventHandler PutFailure; - /// - /// 进度提示事件 - /// - public event Action Progress; Settings putSetting; @@ -72,7 +60,6 @@ public ResumablePutExtra Extra /// public ResumablePut(Settings putSetting, ResumablePutExtra extra) { - extra.chunkSize = putSetting.ChunkSize; this.putSetting = putSetting; this.extra = extra; } @@ -95,19 +82,17 @@ public CallRet PutFile(string upToken, string localFile, string key) using (FileStream fs = File.OpenRead(localFile)) { int block_cnt = block_count(fs.Length); - fsize = fs.Length; - chunks = fsize / extra.chunkSize + 1; + long fsize = fs.Length; extra.Progresses = new BlkputRet[block_cnt]; - //并行上传 byte[] byteBuf = new byte[BLOCKSIZE]; int readLen = BLOCKSIZE; for (int i = 0; i < block_cnt; i++) { - if ((long)(i + 1) * BLOCKSIZE > fsize) + if (i == (block_cnt - 1)) { readLen = (int)(fsize - (long)i * BLOCKSIZE); + } fs.Seek((long)i * BLOCKSIZE, SeekOrigin.Begin); fs.Read(byteBuf, 0, readLen); - //并行上传BLOCK BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen); if (blkRet == null) { @@ -118,14 +103,10 @@ public CallRet PutFile(string upToken, string localFile, string key) extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i])); } } - ret = Mkfile(client, key, fs.Length); + ret = Mkfile(client, key, fsize); } if (ret.OK) { - if (Progress != null) - { - Progress(1.0f); - } if (PutFinished != null) { PutFinished(this, ret); @@ -141,63 +122,43 @@ public CallRet PutFile(string upToken, string localFile, string key) return ret; } - - /// - /// 百分比进度提示 - /// - private void progress() - { - uploadedChunks++; - if (Progress != null) - { - Progress((float)uploadedChunks / chunks); - } - } - private BlkputRet ResumableBlockPut(Client client, byte[] body, int blkIdex, int blkSize) { - int bodyLength; - int chunkSize = extra.chunkSize; #region Mkblock - if (extra.Progresses[blkIdex] == null) + uint crc32 = CRC32.CheckSumBytes(body, blkSize); + for (int i = 0; i < putSetting.TryTimes; i++) { - uint crc32 = CRC32.CheckSumBytes(body,blkSize); - for (int i = 0; i < putSetting.TryTimes; i++) + try { - try - { - extra.Progresses[blkIdex] = Mkblock(client, body, blkSize); - } - catch (Exception ee) - { - if (i == (putSetting.TryTimes - 1)) - { - throw ee; - } - System.Threading.Thread.Sleep(1000); - continue; - } - if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) + extra.Progresses[blkIdex] = Mkblock(client, body, blkSize); + } + catch (Exception ee) + { + if (i == (putSetting.TryTimes - 1)) { - if (i == (putSetting.TryTimes - 1)) - { - return null; - } - System.Threading.Thread.Sleep(1000); - continue; + throw ee; } - else + System.Threading.Thread.Sleep(1000); + continue; + } + if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32) + { + if (i == (putSetting.TryTimes - 1)) { - progress(); - break; + return null; } + System.Threading.Thread.Sleep(1000); + continue; + } + else + { + break; } } #endregion return extra.Progresses[blkIdex]; - } - + } private BlkputRet Mkblock(Client client, byte[] firstChunk, int blkSize) { diff --git a/Qiniu/IO/Resumable/Settings.cs b/Qiniu/IO/Resumable/Settings.cs index 4c98e784..e439950b 100644 --- a/Qiniu/IO/Resumable/Settings.cs +++ b/Qiniu/IO/Resumable/Settings.cs @@ -6,14 +6,13 @@ namespace Qiniu.IO.Resumable /// public class Settings { - int chunkSize; - /// /// chunk大小,默认为4MB; + /// 兼容保留 /// public int ChunkSize { - get { return chunkSize; } - set { chunkSize = value; } + get; + set; } int tryTimes; @@ -33,8 +32,8 @@ public int TryTimes { /// 失败重试次数,默认为3 public Settings (int chunkSize=1 << 22, int tryTimes=3) { - //取消chunk - this.chunkSize = 1 << 22; + //chunkSize 已经删除,兼容保留 + this.tryTimes = tryTimes; } } From b810da23bb35cc8ed1be79981fc1d55a3dc2d394 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Tue, 25 Feb 2014 16:25:43 +0800 Subject: [PATCH 10/16] Fix --- csharp-sdk.2.0.sln | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/csharp-sdk.2.0.sln b/csharp-sdk.2.0.sln index 3a6a6cd5..d3f062ea 100644 --- a/csharp-sdk.2.0.sln +++ b/csharp-sdk.2.0.sln @@ -7,8 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.2.0", "Qiniu\Qiniu.2. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.2.0.Test", "Qiniu.Test\Qiniu.2.0.Test.csproj", "{95DC2A77-2344-4315-9F6F-334CC928459C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qiniu.Demo", "Demo\Qiniu.Demo\Qiniu.Demo.csproj", "{6684C419-1723-4792-A567-7F1D821B6DFA}" -EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = csharp-sdk.vsmdi @@ -44,16 +42,6 @@ Global {95DC2A77-2344-4315-9F6F-334CC928459C}.Release|Mixed Platforms.Build.0 = Release|Any CPU {95DC2A77-2344-4315-9F6F-334CC928459C}.Release|x86.ActiveCfg = Release|Any CPU {95DC2A77-2344-4315-9F6F-334CC928459C}.Release|x86.Build.0 = Release|Any CPU - {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|Any CPU.ActiveCfg = Debug|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|x86.ActiveCfg = Debug|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Debug|x86.Build.0 = Debug|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|Any CPU.ActiveCfg = Release|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|Mixed Platforms.Build.0 = Release|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|x86.ActiveCfg = Release|x86 - {6684C419-1723-4792-A567-7F1D821B6DFA}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From b5500f96eb3d4e1983c21dbd4766ddaebd72b3b4 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Wed, 26 Feb 2014 09:22:56 +0800 Subject: [PATCH 11/16] fix --- Qiniu/IO/Resumable/ResumablePut.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 8e854f5a..b6ed3777 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -88,7 +88,7 @@ public CallRet PutFile(string upToken, string localFile, string key) int readLen = BLOCKSIZE; for (int i = 0; i < block_cnt; i++) { - if (i == (block_cnt - 1)) { + if (i == block_cnt - 1) { readLen = (int)(fsize - (long)i * BLOCKSIZE); } fs.Seek((long)i * BLOCKSIZE, SeekOrigin.Begin); From 352bb1e7ae73b9594ac504e4e0b88239a47c4f89 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Thu, 27 Mar 2014 15:30:07 +0800 Subject: [PATCH 12/16] add travis icon --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0c9be7a4..08e4f3e8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Qiniu Resource (Cloud) Storage SDK for C# + # 关于 此 C# SDK 适用于 .NET2.0 及以上版本,基于 [七牛云存储官方API](http://developer.qiniu.com/docs/v6/api/) 构建。使用此 SDK 构建您的网络应用程序,能让您以非常便捷地方式将数据安全地存储到七牛云存储上。无论您的网络应用是一个网站程序,还是包括从云端(服务端程序)到终端(手持设备应用)的架构的服务或应用,通过七牛云存储及其 SDK,都能让您应用程序的终端用户高速上传和下载,同时也让您的服务端更加轻盈。 From a43477555705bb6801afb3def74c61ca39d5693e Mon Sep 17 00:00:00 2001 From: Bai Long Date: Thu, 3 Apr 2014 15:04:35 +0800 Subject: [PATCH 13/16] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 08e4f3e8..d62b0253 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Qiniu Resource (Cloud) Storage SDK for C# - +[![Build Status](https://api.travis-ci.org/qiniu/csharp-sdk.png?branch=master)](https://travis-ci.org/qiniu/csharp-sdk) + # 关于 此 C# SDK 适用于 .NET2.0 及以上版本,基于 [七牛云存储官方API](http://developer.qiniu.com/docs/v6/api/) 构建。使用此 SDK 构建您的网络应用程序,能让您以非常便捷地方式将数据安全地存储到七牛云存储上。无论您的网络应用是一个网站程序,还是包括从云端(服务端程序)到终端(手持设备应用)的架构的服务或应用,通过七牛云存储及其 SDK,都能让您应用程序的终端用户高速上传和下载,同时也让您的服务端更加轻盈。 From b4cb7aa38c82f6314325bdaf790a10d551ec2d57 Mon Sep 17 00:00:00 2001 From: Bai Long Date: Thu, 3 Apr 2014 15:06:53 +0800 Subject: [PATCH 14/16] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d62b0253..b50a66aa 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ## 许可证 -Copyright (c) 2012 qiniutek.com +Copyright (c) 2014 qiniu.com 基于 MIT 协议发布: From 48a9e502446350c6d93c5ab6250e2dd5ba26caa0 Mon Sep 17 00:00:00 2001 From: icattlecoder Date: Thu, 10 Apr 2014 15:33:23 +0800 Subject: [PATCH 15/16] fix docs --- Docs/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Docs/README.md b/Docs/README.md index de9e53cb..909c62e5 100644 --- a/Docs/README.md +++ b/Docs/README.md @@ -58,6 +58,8 @@ DLL引用方式: C# SDK引用了第三方的开源项目 Json.NET,因此,您需要在项目中引用它 项目地址:[http://json.codeplex.com](http://json.codeplex.com)。 + +## 初始化 ### 配置密钥 @@ -424,7 +426,7 @@ public static void PutFile(string bucket, string key, string fname) { var policy = new PutPolicy(bucket, 3600); string upToken = policy.Token(); - PutExtra extra = new PutExtra(); + PutExtra extra = new PutExtra (); IOClient client = new IOClient(); client.PutFile(upToken, key, fname, extra); } @@ -445,13 +447,12 @@ public static void ResumablePutFile(string bucket, string key, string fname) string upToken = policy.Token(); Settings setting = new Settings(); ResumablePutExtra extra = new ResumablePutExtra(); - extra.Bucket = bucket; ResumablePut client = new ResumablePut(setting, extra); client.PutFile(upToken, fname, Guid.NewGuid().ToString()); } ``` -ResumablePut采用分快上传,各快之间采用并行上传,通过注册事件Progress可以获取当前文件上传进度,同时您也可以通过注册ResumablePutExtra以下两个事件监听当前上传进度以及成功情况: +ResumablePut采用分快上传,各快之间采用并行上传,可以通过注册ResumablePutExtra以下两个事件监听当前上传进度以及成功情况: ```c# public event EventHandler Notify; From 5b66eccd1c5ad5b1426747d9387c20d411f51442 Mon Sep 17 00:00:00 2001 From: longbai Date: Mon, 28 Apr 2014 10:46:17 +0800 Subject: [PATCH 16/16] change log update --- CHANGELOG.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7ea0175..53bd8c56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,9 @@ ## CHANGE LOG - ### v6.1.1 -2014-02-25 issue [#42](https://github.com/qiniu/csharp-sdk/pull/42) - -- 简化断点续上传,删除bput逻辑 -- 修复bug:>2.5GB文件上传失败 +2014-04-28 issue [#45](https://github.com/qiniu/csharp-sdk/pull/45) +- [#41] [#42] 简化断点续上传,删除bput逻辑, 修复bug:>2.5GB文件上传失败 +- [#38] [#40] pfop 支持 ### v6.1.0