diff --git a/Qiniu.Test/IO/Resumable/ResumablePutTest.cs b/Qiniu.Test/IO/Resumable/ResumablePutTest.cs index aa771be2..3cbb0915 100644 --- a/Qiniu.Test/IO/Resumable/ResumablePutTest.cs +++ b/Qiniu.Test/IO/Resumable/ResumablePutTest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Specialized; using System.IO; using NUnit.Framework; using Qiniu.IO.Resumable; @@ -25,6 +26,9 @@ public void ResumablePutFileTest() Settings putSetting = new Settings(); // TODO: 初始化为适当的值 string key=NewKey; ResumablePutExtra extra = new ResumablePutExtra(); + NameValueCollection nc = new NameValueCollection (); + nc.Add("x:username","qiniu"); + extra.CallbackParams = nc; extra.Notify += new EventHandler(extra_Notify); extra.NotifyErr += new EventHandler(extra_NotifyErr); extra.Bucket = Bucket; @@ -39,7 +43,7 @@ public void ResumablePutFileTest() RSHelper.RSDel (Bucket, key); } }); - target.PutFile (upToken, file.FileName, key); + CallRet ret =target.PutFile (upToken, file.FileName, key); //Action a = new Action (() => //{ diff --git a/Qiniu/IO/Resumable/ResumablePut.cs b/Qiniu/IO/Resumable/ResumablePut.cs index 4abe0cde..bb687cc7 100644 --- a/Qiniu/IO/Resumable/ResumablePut.cs +++ b/Qiniu/IO/Resumable/ResumablePut.cs @@ -19,16 +19,24 @@ public class ResumablePut private const int blockMashk = (1 << blockBits) - 1; private static int BLOCKSIZE = 4 * 1024 * 1024; private const string UNDEFINED_KEY = "?"; + #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; @@ -71,7 +79,7 @@ public ResumablePut (Settings putSetting, ResumablePutExtra extra) /// 上传Token /// key /// 本地文件名 - public void PutFile (string upToken, string localFile, string key) + public CallRet PutFile (string upToken, string localFile, string key) { PutAuthClient client = new PutAuthClient (upToken); using (FileStream fs = File.OpenRead(localFile)) { @@ -80,8 +88,7 @@ public void PutFile (string upToken, string localFile, string key) chunks = fsize / extra.chunkSize + 1; extra.Progresses = new BlkputRet[block_cnt]; //并行上传 - Parallel.For (0, block_cnt, (i) => - { + Parallel.For (0, block_cnt, (i) => { int readLen = BLOCKSIZE; if ((i + 1) * BLOCKSIZE > fsize) readLen = (int)(fsize - i * BLOCKSIZE); @@ -89,27 +96,34 @@ public void PutFile (string upToken, string localFile, string key) lock (fs) { fs.Seek (i * BLOCKSIZE, SeekOrigin.Begin); fs.Read (byteBuf, 0, readLen); - BlkputRet blkRet = ResumableBlockPut (client, byteBuf, i, readLen); - if (blkRet == null) { - extra.OnNotifyErr (new PutNotifyErrorEvent (i, readLen, "Make Block Error")); - } else { - extra.OnNotify (new PutNotifyEvent (i, readLen, extra.Progresses [i])); - } } + BlkputRet blkRet = ResumableBlockPut (client, byteBuf, i, readLen); + + if (blkRet == null) { + extra.OnNotifyErr (new PutNotifyErrorEvent (i, readLen, "Make Block Error")); + } else { + extra.OnNotify (new PutNotifyEvent (i, readLen, extra.Progresses [i])); + } + }); if (string.IsNullOrEmpty (key)) { key = UNDEFINED_KEY; } CallRet ret = Mkfile (client, key, fs.Length); - if (Progress != null) { - Progress (1.0f); - } - if (PutFinished != null) { - PutFinished (this, ret); + if (ret.OK) { + if (Progress != null) { + Progress (1.0f); + } + if (PutFinished != null) { + PutFinished (this, ret); + } + } else { + if (PutFailure != null) { + PutFailure (this, ret); + } } - + return ret; } - } /// @@ -147,8 +161,9 @@ private BlkputRet ResumableBlockPut (Client client, byte[] body, int blkIdex, in } } #endregion + #region PutBlock - while (extra.Progresses[blkIdex].offset < blkSize) { + 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); @@ -194,17 +209,23 @@ private BlkputRet BlockPut (Client client, BlkputRet ret, Stream body, long leng private CallRet Mkfile (Client client, string key, long fsize) { - EntryPath entry = new EntryPath (extra.Bucket, key); - string url = string.Format ("{0}/rs-mkfile/{1}/fsize/{2}/", Config.UP_HOST, entry.Base64EncodedURI, fsize); + StringBuilder urlBuilder = new StringBuilder (); + + urlBuilder.AppendFormat ("{0}/mkfile/{1}/key/{2}", Config.UP_HOST, fsize, key.ToBase64URLSafe ()); if (!string.IsNullOrEmpty (extra.MimeType)) { - url += (string.Format ("/mimeType/{0}", extra.MimeType.ToBase64URLSafe ())); + urlBuilder.AppendFormat ("/mimeType/{0}", extra.MimeType.ToBase64URLSafe ()); } if (!string.IsNullOrEmpty (extra.CustomMeta)) { - url += (string.Format ("/meta/{0}", extra.CustomMeta.ToBase64URLSafe ())); + urlBuilder.AppendFormat ("/meta/{0}", extra.CustomMeta.ToBase64URLSafe ()); } - if (!string.IsNullOrEmpty (extra.CallbackParams)) { - url += (string.Format ("/params/{0}", extra.CallbackParams.ToBase64URLSafe ())); + if (extra.CallbackParams != null && extra.CallbackParams.Count > 0) { + StringBuilder sb = new StringBuilder (); + foreach (string _key in extra.CallbackParams.Keys) { + sb.AppendFormat ("/{0}/{1}", _key, extra.CallbackParams [_key].ToBase64URLSafe ()); + } + urlBuilder.Append (sb.ToString ()); } + int proCount = extra.Progresses.Length; using (Stream body = new MemoryStream()) { for (int i = 0; i < proCount; i++) { @@ -215,7 +236,7 @@ private CallRet Mkfile (Client client, string key, long fsize) } } body.Seek (0, SeekOrigin.Begin); - return client.CallWithBinary (url, "text/plain", body, body.Length); + return client.CallWithBinary (urlBuilder.ToString (), "text/plain", body, body.Length); } } diff --git a/Qiniu/IO/Resumable/ResumablePutExtra.cs b/Qiniu/IO/Resumable/ResumablePutExtra.cs index 78506b6d..52894b70 100644 --- a/Qiniu/IO/Resumable/ResumablePutExtra.cs +++ b/Qiniu/IO/Resumable/ResumablePutExtra.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Specialized; namespace Qiniu.IO.Resumable { @@ -69,7 +70,8 @@ public PutNotifyErrorEvent (int blkIdx, int blkSize, string error) /// public class ResumablePutExtra { - public string CallbackParams; + //key format as: "x:var" + public NameValueCollection CallbackParams; public string Bucket; public string CustomMeta; public string MimeType;