.net 中实现php rawurlencode方法(RFC3986)

在对接api时候,经常需要对字符串进行各种编码处理,系统可能是异构的,实现语言也就可能是不一样的。所以经常会使人犯一些2B的错误!

比如:php实现的api中用了rawurlencode,文档中写,需要对字符串进行urlencode编码,.net的开发人员看到文档,直接使用HttpUtitlity.UrlEncode,

   本以为问题已经解决,实际埋下了一个大坑!

  其实php的rawurlincode 实现的是RFC3986,.NET(c#)的HttpUtility.UrlEncode实现的并不是RFC3986!所以对同一个字符串编码当然可能产生不同的结果!

关键是这种问题,很难意识到并去解决!所以,以后遇到类似的问题,一定要记得:要面向协议思考、解决问题,否则...

  下面附上C#对RFC3986的实现:

   /// <summary>
    /// Provides implementation of RFC3986 Percent Encoding mechanism.
    /// </summary>
    public class RFC3986Encoder
    {
        /// <summary>
        /// Performs upper case percent encoding against the specified <paramref name="input"/>.
        /// </summary>
        /// <param name="input">The string to encode.</param>
        /// <returns>Encode string.</returns>
        public static string Encode(string input)
        {
            if (string.IsNullOrEmpty(input))
                return input;
 
            StringBuilder newStr = new StringBuilder();
 
            foreach (var item in input)
            {
                if (IsReverseChar(item))
                {
                    newStr.Append("%");
                    var temp = ((int)item).ToString("X2");
                    newStr.Append(temp);
                }
                else
                    newStr.Append(item);
            }
             
            return newStr.ToString();
        }
 
        /// <summary>
        /// Performs lower case percent encoding (url-encodes) on the <paramref name="input"/> as what HttpUtility.UrlEncode does.
        /// </summary>
        /// <param name="input">The string to encode.</param>
        /// <returns>Encode string.</returns>
        public static string UrlEncode(string input)
        {
            StringBuilder newBytes = new StringBuilder();
            var urf8Bytes = Encoding.UTF8.GetBytes(input);
            foreach (var item in urf8Bytes)
            {
                if (IsReverseChar((char)item))
                {
                    newBytes.Append('%');
                    newBytes.Append(ByteToHex(item));
 
                }
                else
                    newBytes.Append((char)item);
            }
 
            return newBytes.ToString();
        }
 
        private static bool IsReverseChar(char c)
        {
            return !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
                    || c == '-' || c == '_' || c == '.' || c == '~');
        }
 
        private static string ByteToHex(byte b)
        {
            return b.ToString("x2");
        }
 
        private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, 0);
 
        /// <summary>
        /// Gets the seconds from 1970/1/1.
        /// </summary>
        /// <param name="time">The time to calculate from.</param>
        /// <returns>The seconds.</returns>
        public static int ToUnixTime(DateTime time)
        {
            return (int)(time.ToUniversalTime() - UnixEpoch).TotalSeconds;
        }
    }
原文地址:https://www.cnblogs.com/yako/p/3346099.html