Skip to content

Release 6.1.1 #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Apr 28, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## CHANGE LOG

### v6.1.1
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

2014-02-18 issue [#37](https://github.com/qiniu/csharp-sdk/pull/37)
Expand Down
33 changes: 5 additions & 28 deletions Docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ DLL引用方式:
C# SDK引用了第三方的开源项目 Json.NET,因此,您需要在项目中引用它
项目地址:[http://json.codeplex.com](http://json.codeplex.com)。

<a name=setup></a>
## 初始化
<a name=setup-key></a>
### 配置密钥

Expand Down Expand Up @@ -424,18 +426,8 @@ 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<PutRet>((o, ret) => {
if (ret.OK)
{
Console.WriteLine("Hash: " + ret.Hash);
}
else
{
Console.WriteLine("Failed to PutFile");
}
});
client.PutFile(upToken, key, fname, extra);
}
```
Expand All @@ -455,27 +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.Progress += new Action<float>((p) => {
Console.WriteLine("当前进度:{0}%", p * 100);

});
client.PutFinished += new EventHandler<CallRet>((o, ret) => {
if (ret.OK)
{
Console.WriteLine("上传成功:{0}",ret.Response);
}
else
{
Console.WriteLine("上传失败:{0}", ret.Response);
}
});
client.PutFile(upToken, fname, Guid.NewGuid().ToString());
}
```

ResumablePut采用分快上传,各快之间采用并行上传,通过注册事件Progress可以获取当前文件上传进度,同时您也可以通过注册ResumablePutExtra以下两个事件监听当前上传进度以及成功情况
ResumablePut采用分快上传,各快之间采用并行上传,可以通过注册ResumablePutExtra以下两个事件监听当前上传进度以及成功情况

```c#
public event EventHandler<PutNotifyEvent> Notify;
Expand All @@ -498,7 +475,7 @@ public event EventHandler<PutNotifyErrorEvent> NotifyErr;

其中<domain>是bucket所对应的域名。七牛云存储为每一个bucket提供一个默认域名。默认域名可以到[七牛云存储开发者平台](https://portal.qiniu.com/)中,空间设置的域名设置一节查询。用户也可以将自有的域名绑定到bucket上,用户可以通过自有域名访问七牛云存储。

**注意: key必须采用utf8编码,如使用非utf8编码访问七牛云存储将反馈错误**
**注意: key必须采用utf8编码,如使用非utf8编码访问七牛云存储将返回错误**

<a name=private-download></a>
#### 私有资源下载
Expand Down
8 changes: 0 additions & 8 deletions Qiniu.Test/IO/Resumable/ResumablePutTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<float>(target_Progress);
TmpFIle file=new TmpFIle(1024*1024*4);
target.PutFinished += new EventHandler<CallRet> ((o,e) => {
file.Del ();
Expand Down Expand Up @@ -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() + "%");
}
}
}
}
151 changes: 35 additions & 116 deletions Qiniu/IO/Resumable/ResumablePut.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
#if NET40
Expand All @@ -21,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

/// <summary>
/// 上传完成事件
/// </summary>
Expand All @@ -37,10 +30,6 @@ public class ResumablePut
/// 上传Failure事件
/// </summary>
public event EventHandler<CallRet> PutFailure;
/// <summary>
/// 进度提示事件
/// </summary>
public event Action<float> Progress;

Settings putSetting;

Expand Down Expand Up @@ -71,7 +60,6 @@ public ResumablePutExtra Extra
/// <param name="extra"></param>
public ResumablePut(Settings putSetting, ResumablePutExtra extra)
{
extra.chunkSize = putSetting.ChunkSize;
this.putSetting = putSetting;
this.extra = extra;
}
Expand All @@ -88,36 +76,23 @@ public CallRet PutFile(string upToken, string localFile, string key)
{
throw new Exception(string.Format("{0} does not exist", localFile));
}

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;
long fsize = fs.Length;
extra.Progresses = new BlkputRet[block_cnt];
//并行上传
#if NET35||NET20
byte[] byteBuf = new byte[BLOCKSIZE];
int readLen = BLOCKSIZE;
for (int i = 0; i < block_cnt; i++)
{
#elif NET40
Parallel.For(0, block_cnt, (i) =>{
#endif

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);
if (i == block_cnt - 1) {
readLen = (int)(fsize - (long)i * BLOCKSIZE);
}
fs.Seek((long)i * BLOCKSIZE, SeekOrigin.Begin);
fs.Read(byteBuf, 0, readLen);
#if NET40
}
#endif
//并行上传BLOCK
BlkputRet blkRet = ResumableBlockPut(client, byteBuf, i, readLen);
if (blkRet == null)
{
Expand All @@ -127,19 +102,11 @@ public CallRet PutFile(string upToken, string localFile, string key)
{
extra.OnNotify(new PutNotifyEvent(i, readLen, extra.Progresses[i]));
}
#if NET35||NET20
}
#elif NET40
});
#endif
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);
Expand All @@ -155,104 +122,56 @@ public CallRet PutFile(string upToken, string localFile, string key)
return ret;
}


/// <summary>
/// 百分比进度提示
/// </summary>
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++)
{
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);
if (extra.Progresses[blkIdex] == null || crc32 != extra.Progresses[blkIdex].crc32)
{
if (i == (putSetting.TryTimes - 1))
{
return null;
}
continue;
}
else
{
progress();
break;
}
extra.Progresses[blkIdex] = Mkblock(client, body, blkSize);
}
}
#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++)
catch (Exception ee)
{
extra.Progresses[blkIdex] = BlockPut(client, extra.Progresses[blkIdex], new MemoryStream(chunk), bodyLength);
if (extra.Progresses[blkIdex] == null)
if (i == (putSetting.TryTimes - 1))
{
if (i == (putSetting.TryTimes - 1))
{
return null;
}
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))
{
uploadedChunks++;
if (Progress != null)
{
Progress((float)uploadedChunks / chunks);
}
break;
return null;
}
System.Threading.Thread.Sleep(1000);
continue;
}
else
{
break;
}
}
#endregion

return extra.Progresses[blkIdex];
}
}

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<BlkputRet>(callRet.Response);
}
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<BlkputRet>(callRet.Response);
}
return null;
}

private CallRet Mkfile(Client client, string key, long fsize)
{
StringBuilder urlBuilder = new StringBuilder();
Expand Down
2 changes: 1 addition & 1 deletion Qiniu/IO/Resumable/ResumablePutRet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public class BlkputRet
[JsonProperty("crc32")]
public UInt32 crc32;
[JsonProperty("offset")]
public UInt32 offset;
public ulong offset;
}
}
12 changes: 6 additions & 6 deletions Qiniu/IO/Resumable/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ namespace Qiniu.IO.Resumable
/// </summary>
public class Settings
{
int chunkSize;

/// <summary>
/// chunk大小,默认为4MB;
/// 兼容保留
/// </summary>
public int ChunkSize {
get { return chunkSize; }
set { chunkSize = value; }
get;
set;
}

int tryTimes;
Expand All @@ -32,8 +31,9 @@ public int TryTimes {
/// <param name="chunkSize">chunk大小,默认为4MB</param>
/// <param name="tryTimes">失败重试次数,默认为3</param>
public Settings (int chunkSize=1 << 22, int tryTimes=3)
{
this.chunkSize = chunkSize;
{
//chunkSize 已经删除,兼容保留

this.tryTimes = tryTimes;
}
}
Expand Down
3 changes: 1 addition & 2 deletions Qiniu/Qiniu.2.0.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
Expand Down Expand Up @@ -101,4 +100,4 @@
<None Include="app.config" />
</ItemGroup>
<ItemGroup />
</Project>
</Project>
2 changes: 1 addition & 1 deletion Qiniu/Qiniu.4.0.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
Expand Down
Loading