C#使用七牛云存储上传下载文件、自定义回调

项目需要将音视频文件上传服务器,考虑并发要求高,通过七牛来实现。

做了一个简易的压力测试,同时上传多个文件,七牛自己应该有队列处理并发请求,我无论同时提交多少个文件,七牛是批量一个个排队处理了。

一个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信息。

该变量包含子字段,比如对$(exif.ApertureValue.val)取值将得到该图片拍摄时的光圈值。

暂不支持用于saveKey
imageInfo获取所上传图片的基本信息。

该变量包含子字段,比如对$(imageInfo.width)取值将得到该图片的宽度。

暂不支持用于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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543741.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

netfilter que_QUE的完整形式是什么?

netfilter que问题&#xff1a;问题 (QUE: Questions) QUE is an abbreviation of "Questions". QUE是“ Questions”的缩写 。 It is an expression, which is commonly used in the Gmail platform. It is written in the body or the subject of the email to te…

mysqld_multi stop 不能停掉mysql

使用mysqld_multi start 启动了多个mysql&#xff0c;但是mysqld_multi stop 却不能停止原因&#xff1a;因为你还没有授权/usr/local/mysql/bin/mysqld_multi stop 但是默认是停不掉的&#xff0c;需要我们做一个授权grant shutdown on *.* to usernamelocalhost identified…

热冗余冷冗余_冗余支架

热冗余冷冗余Problem statement: 问题陈述&#xff1a; Given a string of balanced expression, find if it contains a redundant parenthesis or not. A set of parentheses is redundant if the same sub-expression is surrounded by unnecessary or multiple brackets. …

对称树

Problem statement: 问题陈述&#xff1a; Given a binary Tree, check whether the tree is symmetric or not. 给定二叉树 &#xff0c; 检查树是否对称 。 Input Example: 输入示例&#xff1a; For example1/ \2 2/ \ / \3 4 4 3The above tree is symmetric1/ \2 …

unity, undo

如果在操作一个Object之前调用Undo.RecordObject(Object)&#xff0c;且操作确实造成Object某些属性的改变&#xff0c;则会产生一个undo记录。 如果我们的架构不是直接操作Object&#xff0c;而是操作一个ui&#xff0c;并在某些时机通过ui.save(Object)将数据回写到Object&am…

ajax应用_AJAX的应用

ajax应用AJAX has several benefits that can be utilized inside a web application. In this article, well explore some advantages of AJAX and see some of its applications. AJAX具有可在Web应用程序内部使用的多个优点。 在本文中&#xff0c;我们将探讨AJAX的一些优势…

Linux下DRBD配置

一、什么是DRBD1、简介 Distributed Replicated Block Device(DRBD)是一个用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案。数据镜像&#xff1a;实时、透明、同步&#xff08;所有服务器都成功后返回&#xff09;、异步&#xff08;本地服务器成功后返回…

键盘特殊_特殊键盘

键盘特殊Problem statement: 问题陈述&#xff1a; Imagine you have a special keyboard with four types of keys: 想象一下&#xff0c;您有一个特殊的键盘&#xff0c;其中包含四种类型的键&#xff1a; Key 1: Prints I on screen 按键1&#xff1a;在屏幕上打印“ I”…

【C++入门】简单的日期类操作

//--------------------------------------------------------------------------/***名称&#xff1a;日期的简单操作******类函数&#xff1a;构造函数&#xff0c;拷贝构造函数&#xff0c;析构函数&#xff0c;操作符重载函数****日期类操作函数&#xff1a; 1&#xff1a;…

Scala山脉

Scala Range Scala山脉 A Range is a bounded series with a uniform interval with an upper and lower limit. The range literal is a numerical sequence of number ranging with a certain limit. 范围是一个有上限且下限均匀的有界序列。 范围文字是具有一定限制的范围…

黑客经验谈:跳板攻击入侵技术实例解析

网络入侵&#xff0c;安全第一,一个高明的入侵者&#xff0c;不会冒然实行动. 他们在入侵时前会做足功课&#xff0c;入侵时会通过各种技术手段保护自己&#xff0c;以防被对方发现&#xff0c;引火烧身. 其中&#xff0c;跳板技术是攻击者通常采用的技术. 下面笔者结合实例&am…

dom属性和html属性_HTML属性

dom属性和html属性Attributes are used to provide additional information of a tag such as it’s alignments, color, size of the text and other. The attributes are given with the tag that is between the angular brackets after the tag name. The attributes have …

科普:UTF-8 GBK UTF8 GB2312 之间的区别和关系

UTF-8&#xff1a;Unicode TransformationFormat-8bit&#xff0c;允许含BOM&#xff0c;但通常不含BOM。是用以解决国际上字符的一种多字节编码&#xff0c;它对英文使用8位&#xff08;即一个字节&#xff09;&#xff0c;中文使用24为&#xff08;三个字节&#xff09;来编码…

vue3实现本地开发使用的px转换成vw,px转换成rem方法整理

前言&#xff1a; 项目中如果想本地开发使用px&#xff0c;但是界面上线以后界面是自适应的效果,可以有多种方式来实现效果。 一、px转成vw 1、安装&#xff0c;安装成功后&#xff0c;node_modules 会新增这两个插件包 npm i postcss-px-to-viewport-8-plugin 2、新增 post…

airplay2协议是什么_什么是AirPlay?

airplay2协议是什么AirPlay (AirPlay) AirPlay is released by Apple in the year 2004. It allows the easy exchange of audios without the use of any wired technique between the two devices. It was previously termed as AirTunes and later got its name changed to …

微信支付开发(5) 订单查询

本文介绍微信支付中订单查询功能的实现。 作者&#xff1a;方倍工作室 地址&#xff1a;http://www.cnblogs.com/txw1958/p/wxpay-order-query.html 一、订单查询 因为某一方技术的原因&#xff0c;可能导致商户在预期时间内都收不到最终支付通知&#xff0c;此时商户可以通过该…

ruby 执行函数_Ruby at()函数

ruby 执行函数Ruby中的at()函数 (at() function in Ruby) If you are working with arrays in Ruby, sometimes you may need to find the element at a particular index. For meeting the purpose, we have got at() function in Ruby which is already defined in Rubys lib…

python饼形图_Python | 饼形图

python饼形图A pie plot or a pie chart is a circular statistical graphic technique, in which a circle is divided into slices with respect to numerical proportion. In a pie chart, the arc length, central angle, and area of each slice, is proportional to the …

Linux巡检

# uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # hostname # 查看计算机名 # lspci -tv # 列出所有PCI设备 # lsusb -tv # 列出所有USB设备 # lsmod # 列出加载的内核模块 # env # 查看环境变量 # fre…

appweb ejs_EJS部分

appweb ejsHi! Welcome. Today, we are going to look at EJS partials. EJS Partials help us avoid repetition of the same code on several web pages. 嗨&#xff01; 欢迎。 今天&#xff0c;我们将看EJS局​​部函数 。 EJS Partials帮助我们避免在多个网页上重复相同的…