C#使用七牛雲存儲上傳下載文件、自定義回調

項目須要將音視頻文件上傳服務器,考慮併發要求高,經過七牛來實現。html

作了一個簡易的壓力測試,同時上傳多個文件,七牛本身應該有隊列處理併發請求,我不管同時提交多少個文件,七牛是批量一個個排隊處理了。java

一個1.5MB的文件,上傳時間大概2-3秒,感受不錯。 算法

 

直接上代碼api

 

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

相關文章
相關標籤/搜索