.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 + "

"+ contentType + "
" + date + "
" + 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、由于是采用的异步上传,其实文件上传后的路径,即为请求地址+文件路径。

您的资助是我最大的动力!
金额随意,欢迎来赏!

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐按钮
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

如果,想给予我更多的鼓励,求打

因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是懒惰的程序员

原文地址:https://www.cnblogs.com/JackXiong/p/10875953.html