C#使用七牛云存储上传下载文件、自定义回调
项目需要将音视频文件上传服务器,考虑并发要求高,通过七牛来实现。做了一个简易的压力测试,同时上传多个文件,七牛自己应该有队列处理并发请求,我无论同时提交多少个文件,七牛是批量一个个排队处理了。一个1.5MB的文件,上传时间大概2-3秒,感觉不错。 直接上代码 using Qiniu.IO;using Qiniu.IO.Resumable;using Qin
·
项目需要将音视频文件上传服务器,考虑并发要求高,通过七牛来实现。
做了一个简易的压力测试,同时上传多个文件,七牛自己应该有队列处理并发请求,我无论同时提交多少个文件,七牛是批量一个个排队处理了。
一个1.5MB的文件,上传时间大概2-3秒,感觉不错。
直接上代码
using Qiniu.IO; using Qiniu.IO.Resumable; using Qiniu.RPC; using Qiniu.RS; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace qiniuTest { /// <summary> /// 文件上传有两种方式: /// 一种是以普通方式直传文件,简称普通上传; /// 另一种方式是断点续上传,断点续上传在网络条件很一般的情况下也能有出色的上传速度,而且对大文件的传输非常友好。 /// </summary> class Program { static string bucket = "cvteXXXX"; static void Main(string[] args) { Qiniu.Conf.Config.ACCESS_KEY = "6QQ7Cnz4bljdkQOWQ5UOAheVCAd0bCa7Tc5XXXXX"; Qiniu.Conf.Config.SECRET_KEY = "9rUGnbFtvm-PLWcZeOR6ed9MUjZ4bKitf7YXXXX"; string fileKey = "应用系统全貌图.png"; //GetFileStat(bucket, fileKey); //小文件直传 string fileName = "CVTE信息系统-业务功能架构图-IM和企业微信.jpg"; //PutFile(bucket, Guid.NewGuid().ToString() + fileName, "d:\\" + fileName); //在asp.net mvc中的文件上传 //ResumablePutFile(bucket, Guid.NewGuid().ToString(), Path.Combine(path, Request.Form[0])); //大文件上传 //string bigFileName = "eclipse-java-luna-SR1-win32-x86_64.zip"; //ResumablePutFile(bucket, Guid.NewGuid().ToString() + bigFileName, "d:\\Software\\" + bigFileName); //GetFile("7xq1c1.com1.z0.glb.clouddn.com", fileKey); //********************** 压力测试 ********************** // 获取线程池的最大线程数和维护的最小空闲线程数 int maxThreadNum, portThreadNum; int minThreadNum; ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum); ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum); Console.WriteLine("最大线程数:{0}", maxThreadNum); Console.WriteLine("最小空闲线程数:{0}", minThreadNum); int loopNumber = 1; //内部循环次数 int ConcurrentNumber = 10; //并发数 for (int i = 0; i < ConcurrentNumber; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), loopNumber); } Console.ReadLine(); } public static void TaskProc(object loopNumber) { int LoopNumber = Convert.ToInt32(loopNumber); Console.WriteLine("启动任务,小文件直传"); //小文件直传 压力测试 for (int i = 0; i < LoopNumber; i++) { string fileName = "WinRAR.exe"; Console.WriteLine(i + "开始" + fileName + System.DateTime.Now); PutFile(bucket, Guid.NewGuid().ToString() + fileName, "D:\\" + fileName); Console.WriteLine(i + "完成" + fileName + System.DateTime.Now); string fileName1 = "WinRAR1.exe"; Console.WriteLine(i + "开始" + fileName1 + System.DateTime.Now); PutFile(bucket, Guid.NewGuid().ToString() + fileName1, "D:\\" + fileName1); Console.WriteLine(i + "完成" + fileName1 + System.DateTime.Now); } } /// <summary> /// 查看单个文件属性信息 /// </summary> /// <param name="bucket">七牛云存储空间名</param> /// <param name="key">文件key,也就是文件名</param> public static void GetFileStat(string bucket, string key) { RSClient client = new RSClient(); Entry entry = client.Stat(new EntryPath(bucket, key)); if (entry.OK) { Console.WriteLine("Hash: " + entry.Hash); Console.WriteLine("Fsize: " + entry.Fsize); Console.WriteLine("PutTime: " + entry.PutTime); Console.WriteLine("MimeType: " + entry.MimeType); Console.WriteLine("Customer: " + entry.Customer); } else { Console.WriteLine("Failed to Stat"); } } /// <summary> /// 删除单个文件 /// </summary> /// <param name="bucket">文件所在的空间名</param> /// <param name="key">文件key</param> public static void Delete(string bucket, string key) { Console.WriteLine("\n===> Delete {0}:{1}", bucket, key); RSClient client = new RSClient(); CallRet ret = client.Delete(new EntryPath(bucket, key)); if (ret.OK) { Console.WriteLine("Delete OK"); } else { Console.WriteLine("Failed to delete"); } } /// <summary> /// 批量删除文件 /// </summary> /// <param name="bucket">文件所在的空间名</param> /// <param name="keys">文件key</param> public static void BatchDelete(string bucket, string[] keys) { RSClient client = new RSClient(); List<EntryPath> EntryPaths = new List<EntryPath>(); foreach (string key in keys) { Console.WriteLine("\n===> Stat {0}:{1}", bucket, key); EntryPaths.Add(new EntryPath(bucket, key)); } client.BatchDelete(EntryPaths.ToArray()); } /// <summary> /// 普通方式直传文件 /// </summary> /// <param name="bucket">文件所在的空间名</param> /// <param name="key">您可以自行定义文件Key,一般GUID</param> /// <param name="fname">文件路径+文件名</param> public static void PutFile(string bucket, string key, string fname) { var policy = new PutPolicy(bucket, 3600); string upToken = policy.Token(); PutExtra extra = new PutExtra(); IOClient client = new IOClient(); client.PutFile(upToken, key, fname, extra); } /// <summary> /// 断点续上传方式,传大文件用这种方式 /// </summary> /// <param name="bucket">文件所在的空间名</param> /// <param name="key">您可以自行定义文件Key,一般GUID</param> /// <param name="fname">文件路径+文件名</param> public static void ResumablePutFile(string bucket, string key, string fname) { Console.WriteLine("\n===> ResumablePutFile {0}:{1} fname:{2}", bucket, key, fname); PutPolicy policy = new PutPolicy(bucket, 3600); string upToken = policy.Token(); Settings setting = new Settings(); ResumablePutExtra extra = new ResumablePutExtra(); ResumablePut client = new ResumablePut(setting, extra); client.PutFile(upToken, fname, Guid.NewGuid().ToString()); } /// <summary> /// Get方式获取文件 /// </summary> /// <param name="domain">文件域</param> /// <param name="key">文件Key</param> public static void GetFile(string domain, string key) { System.Diagnostics.Process.Start("http://" + domain + "/" + key); } } }
另外,七牛的魔法变量非常强大,多用于增强回调
魔法变量
魔法变量是一组预先定义的变量,可以使用 $(var)
或 $(var.field_name)
形式求值。
目前可用的魔法变量如下:
变量名 | 包含子项 | 变量说明 | 适用范围 |
bucket | 获得上传的目标空间名。 | ||
key | 获得文件保存在空间中的资源名。 | ||
etag | 文件上传成功后的HTTP ETag。若上传时未指定资源ID,Etag将作为资源ID使用。 | ||
fname | 上传的原始文件名。 | 不支持用于分片上传 | |
fsize | 资源尺寸,单位为字节。 | ||
mimeType | 资源类型,比如JPG图片的资源类型为image/jpg 。 | ||
endUser | 上传时指定的endUser 字段,通常用于区分不同终端用户的请求。 | ||
persistentId | 音视频转码持久化的进度查询ID。 | ||
exif | 是 | 获取所上传图片的Exif信息。 该变量包含子字段,比如对 | 暂不支持用于saveKey 中 |
imageInfo | 是 | 获取所上传图片的基本信息。 该变量包含子字段,比如对 | 暂不支持用于saveKey 中 |
year | 上传时的年份。 | 暂不支持用于’returnBody’、’callbackBody’中 | |
mon | 上传时的月份。 | 暂不支持用于’returnBody’、’callbackBody’中 | |
day | 上传时的日期。 | 暂不支持用于’returnBody’、’callbackBody’中 | |
hour | 上传时的小时。 | 暂不支持用于’returnBody’、’callbackBody’中 | |
min | 上传时的分钟。 | 暂不支持用于’returnBody’、’callbackBody’中 | |
sec | 上传时的秒钟。 | 暂不支持用于’returnBody’、’callbackBody’中 | |
avinfo | 是 | 音视频资源的元信息。 | 暂不支持用于’saveKey’中 |
imageAve | 图片主色调,算法由Camera360友情提供。 | ||
ext | 上传资源的后缀名,通过自动检测的 mimeType 或者原文件的后缀来获取。 | 不支持用于分片上传 | |
uuid | 生成uuid | 暂不支持用于’saveKey’中 | |
bodySha1 | callbackBody的sha1(hex编码) | 只支持用于’callbackUrl’中 |
魔法变量支持$(<Object>.<Property>)
形式的访问子项,例如:
- $(<var>)
- $(<var>.<field_name>)
- $(<var>.<field_name>.<sub_field_name>)
求值举例:
$(bucket)
- 获得上传目标bucket名字$(imageInfo)
- 获取当前上传图片的基本属性信息$(imageInfo.height)
- 获取当前上传图片的原始高度
回调通知(callback)
可以设置上传策略(PutPolicy)中的callbackUrl
字段,并且设置callbackBody
字段。
“自定义回调”具体实现
/// <summary> /// 文件上传后的自定义回调 /// </summary> /// <param name="bucket">文件所在的空间名</param> /// <param name="key">您可以自行定义文件Key,一般GUID</param> /// <param name="fname">文件路径+文件名</param> public static PutRet PutFile(string bucket, string key, string fname) { var policy = new PutPolicy(bucket, 3600); policy.ReturnBody = "{\"key\": $(key), \"hash\": $(etag), \"extra\": $(x:extra), \"callbackUrl\": $(x:callbackUrl)}"; //policy.CallBackBody = "name=$(fname)&location=$(x:location)&price=$(x:price)"; //policy.CallBackUrl = "http://ip/url"; string upToken = policy.Token(); PutExtra extra = new PutExtra(); //扩展属性 Dictionary<string,string> dict =new Dictionary<string,string>(); dict.Add("x:extra", "location=shanghai&age=28"); dict.Add("x:callbackUrl", "http://127.0.0.1/callback"); extra.Params = dict; IOClient client = new IOClient(); return client.PutFile(upToken, key, fname, extra); }
完整源代码下载 :source code
更多推荐
已为社区贡献1条内容
所有评论(0)