.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;

        }

    }

 

你可能感兴趣的:(encode)