.NET CORE 對接天翼雲 OOS


最近,因公司項目需要對接天翼雲OOS,在百度多次折騰后,大部分的都是基於java、php 等其他語言,很少基於C#語言的相關資料,即使有也是基於.NET Framwork開發的SDK,內容幾乎是千篇一律,很少基於.NET CORE的開發。在官網上也很少發現基於C#語言的身影,最終在網上找尋到OOS相關的SDK集合中找到基於.NET(C#) SDK開發包

根據SDK開發包指引迫不及待的在.NET CORE 項目中嘗試,但最終還是以失敗告終。然后再.NET Framework 環境中居然能成功,百思不得其解,於是聯系聯系電信售后那邊,最終從電信技術人員口中得知,不支持.NET CORE。

 

最終,參考OOS開發者文檔,采用調用http接口的方式實現,惱火的部分,不是接口的調用,而是簽名算法,這個折騰了好幾天,最終采用將文檔中的java代碼翻譯成C#代碼搞定。第一次寫博客,那直接就上代碼,通過下面的封裝既可以在.NET Framework中使用,也可以在.NET core中使用,

 

第一步:實現簽名算法:

 

    /// <summary>
    /// 天翼雲OOS簽名V2版本
    /// </summary>
    public class CtyunOOSSignatureV2
    {
        /// <summary>
        /// 賬號
        /// </summary>
        private String secretkey;

        /// <summary>
        /// 秘鑰
        /// </summary>
        private string accessKey;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="secretkey">秘鑰</param>
        /// <param name="accessKey">賬號</param>
        /// <param name="region"></param>
        public CtyunOOSSignatureV2(string accessKey,String secretkey)
        {
            this.secretkey = secretkey;
            this.accessKey = accessKey;
        }

        /// <summary>

        /// HMACSHA1算法加密並返回ToBase64String

        /// </summary>

        /// <param name="strText">簽名參數字符串</param>

        /// <param name="strKey">密鑰參數</param>

        /// <returns>返回一個簽名值(即哈希值)</returns>

        private string ToBase64hmac(string strKey, string strText)

        {

            HMACSHA1 myHMACSHA1 = new HMACSHA1(Encoding.UTF8.GetBytes(strKey));

            byte[] byteText = myHMACSHA1.ComputeHash(Encoding.UTF8.GetBytes(strText));

            return System.Convert.ToBase64String(byteText);

        }


        private string GetStringToSign(string httpVerb, String contentType, string date, string uri)
        {
            String stringToSign = httpVerb + "\n\n"+ contentType + "\n" + date + "\n" + uri;


            return stringToSign;
        }
        
        /// <summary>
        /// 獲取認證簽名信息
        /// </summary>
        /// <param name="httpVerb">請求方法</param>
        /// <param name="date">請求時間</param>
        /// <param name="uri">存儲桶</param>
        /// <param name="objectname">存儲對象名稱</param>
        /// <returns></returns>
        public string AuthorizationSignature(string httpVerb,String contentType, string date, string uri)
        {

            var stringToSign = GetStringToSign(httpVerb, contentType,date, uri);

            var signature = ToBase64hmac(this.secretkey, stringToSign);

            return "AWS " + this.accessKey + ":" + signature;

        }
    }

 

第二步:實現接口調用:

 

 public interface IOOSHelper
    {
        /// <summary>
        /// 設置配置信息
        /// </summary>
        /// <param name="serviceURL">雲地址</param>
        /// <param name="accessKey">oos賬號</param>
        /// <param name="secretKey">oos密碼</param>
        /// <param name="bucketName">存儲桶</param>
        void InitOOSHelper(string serviceURL, string accessKey, string secretKey, string bucketName);


        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <param name="objectname">商戶號+文件名稱,例如:99999/1.JPG</param>
        /// <param name="msg">如果成功返回文件存儲地址;失敗返回錯誤原因</param>
        /// <returns></returns>
        Boolean UploadFile(Stream inputStream, string objectname,ref string msg);
    }

  

    public class CtyunOOSHttpHelper : IOOSHelper
    {
        private readonly String root_dir = "WeChatApp";
        /// <summary>
        /// 天翼雲oos賬號
        /// </summary>
        private string _accessKey;

        /// <summary>
        /// 天翼雲oos密碼
        /// </summary>
        private string _secretKey;

        /// <summary>
        /// 存儲桶
        /// </summary>
        private string _bucketName;

        /// <summary>
        /// 天翼雲地址
        /// </summary>
        private string _serviceURL;

        private CtyunOOSSignatureV2 signature;

        public void InitOOSHelper(string serviceURL, string accessKey, string secretKey, string bucketName)
        {
            this._serviceURL = serviceURL;
            this._accessKey = accessKey;
            this._secretKey = secretKey;
            this._bucketName = bucketName;

            signature = new CtyunOOSSignatureV2(accessKey, secretKey);

        }

        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <param name="objectname">商戶號+文件名稱,例如:99999/1.JPG</param>
        /// <param name="msg">如果成功返回文件存儲地址;失敗返回錯誤原因</param>
        /// <returns></returns>
        public bool UploadFile(Stream stream, string objectname,ref String msg)
        {
            Boolean success = true;
           
            int filelength = 0;

            filelength = (int)stream.Length; //獲得文件長度 

            byte[] data = new Byte[filelength]; //建立一個字節數組 

            stream.Read(data, 0, filelength); //按字節流讀取 

            HttpRequestHelper httpReqHelper = new HttpRequestHelper(this._serviceURL);

            string uri = this._bucketName + "/" + root_dir+ "/" + objectname;

            String datetime = DateTime.Now.ToUniversalTime().ToString("R"); 

            var authorization = signature.AuthorizationSignature(HttpRequestHelper.HttpType.PUT.ToString(), "image/jpeg", datetime, "/" + uri);

            Dictionary<String, string> headers = new Dictionary<string, string>();

            headers.Add("Date", datetime);
            headers.Add("Content-Type", "image/jpeg");
            headers.Add("Authorization", authorization);
            try
            {
                httpReqHelper.AddRequestHeaders(headers);
               msg= httpReqHelper.HttpRequest(uri, HttpRequestHelper.HttpType.PUT, data);

                if (String.IsNullOrEmpty(msg))
                    msg = this._serviceURL +"/"+ uri;

            }
            catch (Exception ex)
            {
                msg= ex.Message;
                success = false;
            }
            return success;
        }
    }

 

第三步:編寫單元測試

 [TestClass]
    public class UnitOOSTest
    {

        private static String accessKey = "b7f***********bb13c4f6";
        private static String secretKey = "9e1739f4986ba***********a4f85b20bdcf";
        // API 服務器
        private static String OOS_SERVICE = "http://oos-***.ctyunapi.cn";
        private static String bucketName = "dx-****-dev";

        [TestMethod]
        public void TestOOSUploadFile()
        {

            IOOSHelper ctyunOOSHelper = new CtyunOOSHttpHelper();
         
            ctyunOOSHelper.InitOOSHelper(OOS_SERVICE, accessKey, secretKey, bucketName);

            string msg=string.Empty;

            using (var fs = new FileStream(@"f:\181256.jpg", FileMode.Open))
            {

                ctyunOOSHelper.UploadFile(fs, "1121212/181256.jpg", ref msg);
            }

            Console.ReadKey();
        }
    }

  以上即是調用OOS的全部代碼。

 

以上項目中用到httphelper幫助類:

    public class HttpRequestHelper
    {
        private static string BaseUri;

        /// <summary>
        /// 
        /// </summary>
        private Dictionary<String, string> headers;

        public HttpRequestHelper(string baseUri)
        {
            BaseUri = baseUri;
        }


        #region Delete方式
        private   string Delete(string uri, byte[] data)
        {
            string serviceUrl = "";
            if (BaseUri == "" || BaseUri == null)
            {
                serviceUrl = uri;
            }
            else
            {
                serviceUrl = string.Format("{0}/{1}", BaseUri, uri);
            }
            return CommonHttpRequest(serviceUrl, "DELETE", data);
        }
        #endregion
        #region Put方式
        private   string Put(string uri, byte[] data)
        {
            string serviceUrl = "";
            if (BaseUri == "" || BaseUri == null)
            {
                serviceUrl = uri;
            }
            else
            {
                serviceUrl = string.Format("{0}/{1}", BaseUri, uri);
            }
            return CommonHttpRequest(serviceUrl, "PUT", data);
        }
        #endregion
        #region POST方式實現


        private   string Post(string uri, byte[] data)
        {
            string serviceUrl = "";
            if (BaseUri == "" || BaseUri == null)
            {
                serviceUrl = uri;
            }
            else
            {
                serviceUrl = string.Format("{0}/{1}", BaseUri, uri);
            }
            return CommonHttpRequest(serviceUrl, "Post", data);
        }
        #endregion
        #region GET方式實現
        private   string Get(string uri)
        {
            string serviceUrl = "";
            if (BaseUri == "" || BaseUri == null)
            {
                serviceUrl = uri;
            }
            else
            {
                serviceUrl = string.Format("{0}/{1}", BaseUri, uri);
            }
            return CommonHttpRequest(serviceUrl, "GET", null);
        }

        #endregion
        #region  私有方法
        private  string CommonHttpRequest(string url, string reqType, byte[] data)
        {
            HttpWebRequest webRequest = null;
            Stream outstream = null;
            HttpWebResponse myResponse = null;
            StreamReader reader = null;
            try
            {
                //構造http請求的對象
                webRequest = (HttpWebRequest)WebRequest.Create(url);


                //設置
                webRequest.ProtocolVersion = HttpVersion.Version11;
                webRequest.Method = reqType;

                if(headers !=null && headers.Count>0)
                {
                    foreach(var header in headers)
                    webRequest.Headers.Add(header.Key,header.Value);
                }
                
                if (data !=null&&data.Length >0)
                {
                    webRequest.ContentLength = data.Length;
                   
                    //轉成網絡流
                    byte[] buf = data;

                    outstream = webRequest.GetRequestStream();
                    outstream.Flush();
                    outstream.Write(buf, 0, buf.Length);
                    outstream.Flush();
                    outstream.Close();
                }
                // 獲得接口返回值
                myResponse = (HttpWebResponse)webRequest.GetResponse();
                reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
                string ReturnXml = reader.ReadToEnd();
                reader.Close();
                myResponse.Close();
                webRequest.Abort();
                return ReturnXml;
            }
            catch (Exception ex)
            {
                if (outstream != null) outstream.Close();
                if (reader != null) reader.Close();
                if (myResponse != null) myResponse.Close();
                if (webRequest != null) webRequest.Abort();
                throw ex;
            }
        }

        #endregion


        #region 通用請求
        /// <summary>
        /// Http通用請求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="type"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public string HttpRequest(string url, HttpType type, byte[] data)
        {
            switch (type)
            {
                case HttpType.PUT:
                    return Put(url, data);
                case HttpType.GET:
                    return Get(url);
                case HttpType.POST:
                    return Post(url, data);
                case HttpType.DELETE:
                    return Delete(url, data);
                default:
                    break;
            }
            return "";
        }

        /// <summary>
        /// 添加請求頭
        /// </summary>
        /// <param name="headers"></param>
        public void AddRequestHeaders(Dictionary<String,string> headers)
        {
            this.headers = headers;
        }

        /// <summary>
        /// Http通用請求
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="uri"></param>
        /// <param name="type"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public string HttpRequest(string ip, string port, string uri, HttpType type, byte[] data)
        {
            string url = "http://" + ip + ":" + port + uri;
            return HttpRequest(url, type, data);
        }


        #endregion


        public enum HttpType
        {
            PUT = 0,
            GET = 1,
            POST = 2,
            DELETE = 3


        }
    }

 注意事項:

1、根據本人與天翼雲技術溝通,目前他們注意是支持的oos開發者文檔中的v2簽名格式,v4測試過幾次,並沒有通過,如果有實現了的小伙伴可以分享一下,不足之處請多多指教!

2、注意系統調用的時間應該采用DateTime.Now.ToUniversalTime(),而不是DateTime.Now,如果時間不對也無法上傳;

3、由於是采用的異步上傳,其實文件上傳后的路徑,即為請求地址+文件路徑。

 


免責聲明!

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



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