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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM