[转载]HttpUtility.UrlEncode

[转载]HttpUtility.UrlEncode 在 Encode 的时候, 将空格转换成加号(‘+’), 在 Decode 的时候将加号转为空格, 但是浏览器是不能理解加号为空格的, 所以如果文件名包含了空格, 在浏览器下载得到的文件, 空格就变成了加号 – 爱晚红枫技术部广东分部 – 博客园.

在用 ASP.NET 开发页面的时候, 我们常常通过 System.Web.HttpUtility.UrlEncode 和 UrlDecode 在页面间通过 URL 传递参数. 成对的使用 Encode 和 Decode 是没有问题的.

但是, 我们在编写文件下载的页面的时候, 常常用如下方法来指定下载的文件的名称:
Response.AddHeader(
Content-Disposition,attachment; filename=
+ HttpUtility.UrlEncode(fileName, Encoding.UTF8));
之所以转换成 UTF8 是为了支持中文文件名.

这时候问题就来了, 因为 HttpUtility.UrlEncode 在 Encode 的时候, 将空格转换成加号(
+), 在 Decode 的时候将加号转为空格, 但是浏览器是不能理解加号为空格的, 所以如果文件名包含了空格, 在浏览器下载得到的文件, 空格就变成了加号.

一个解决办法是, 在 HttpUtility 的 UrlEncode 之后, 将
+ 替换成 %20( 如果原来是 + 则被转换成 %2b ) , 如:
fileName
= HttpUtility.UrlEncode(fileName, Encoding.UTF8);
fileName
= fileName.Replace(+, %20);
不明白微软为什么要把空格转换成加号而不是
%20. 记得 JDK 的 UrlEncoder 是将空格转换成 %20的.
经检查, 在 .Net
2.0 也是这样.

HttpUtility.UrlEncode 在 Encode 的时候, 将空格转换成加号(+), 在 Decode 的时候将加号转为空格, 但是浏览器是不能理解加号为空格的, 所以如果文件名包含了空格, 在浏览器下载得到的文件, 空格就变成了加号

<html>
<head>
<meta http-equiv=’Content-Type’ content=’text/html; charset=gb2312′>
<title>URL解码(Decode)/编码(Encode)</title>
</head>
<body>
<center><font color=green size=+2>URL解码(Decode)/编码(Encode)</font><br>
需要解码的字符串:
<TEXTAREA ID=”String1″ ROWS=”10″ COLS=”30″></TEXTAREA> 解码后的字符串:<TEXTAREA ID=”String2″ ROWS=”10″ COLS=”30″></TEXTAREA><br>
需要编码的字符串:
<TEXTAREA ID=”String3″ ROWS=”10″ COLS=”30″></TEXTAREA> 编码后的字符串:<TEXTAREA ID=”String4″ ROWS=”10″ COLS=”30″></TEXTAREA><br>
<INPUT TYPE=”button” ID=”Decode” value=”解码(Decode)” onClick=”JavaScript:String2.value=decodeURI(String1.value);”>
<INPUT TYPE=”button” ID=”Encode” value=”编码(Encode)” onClick=”JavaScript:String4.value=encodeURI(String3.value);”>
</center>
</body>
</html>

url传递中文的解决方案总结

1.设置web.config文件。(我不喜欢设置成这样)
<system.web>
……
<globalization requestEncoding=”gb2312″ responseEncoding=”gb2312″ culture=”zh-CN” fileEncoding=”gb2312″ />
……
</system.web>

或者:
aspx文件中:
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>

2.传递中文之前,将要传递的中文参数进行编码,在接收时再进行解码。
>> 进行传递
string Name = “中文参数”;
Response.Redirect(“B.aspx?Name=”+Server.UrlEncode(Name));

>> 进行接收
string Name = Request.QueryString[“Name”];
Response.Write(Server.UrlDecode(Name));
或者:

NavigateURL='<%# “WebForm2.aspx?Singer=” + HttpUtility.UrlEncode(“中国人”, System.Text.Encoding.GetEncoding(“GB2312”)) %>’


3.如果是从 .HTML 文件向 .Aspx 文件进行传递中文参数的话(即不从后台用 Redirect()方法进行 Url 转换)。一样要将传递的中文参数进行编码,在接收时再进行解码。
>> 进行传递
<script language=”JavaScript”>
function GoUrl()
{
var Name = “中文参数”;
location.href = “B.aspx?Name=”+escape(Name);
}
</script>
<body onclick=”GoUrl()”>
>> 进行接收
string Name = Request.QueryString[“Name”];
Response.Write(Server.UrlDecode(Name));

一般来说。设置web.config文件就可以了。但是如果你用 JavaScript 调用 webservice 方法的话(往webservice里面传递中文参数)。设置 web.config 文件好象无效。

————————————————————
在html中实现编解码:

<script language=”javascript”>
function openUrl(src)
{
var strUrl=escape(src);
window.open(strUrl);
}

function change_url(src)
{
document.location.href=escape(src);
}

</script>

在新窗口保存
<a href=’javascript:openUrl(“css/20040603123628交易中心烟叶网上集中交易系统合同.doc”);’ >20040603123628交易中心网上集中交易系统合同</a>

当前位置保存,无闪烁。
<a href=”#” onclick=javascript:change_url(“css/20040603123628交易中心烟叶网上集中交易系统合同.doc”)>20040603123628交易中心网上集中交易系统合同</a>

注意:路径中的斜线是:“/”,而不是“\”,否则也不行啊。

----------------------------------------
前一阵遇到在做.net Web开发时,碰到一个很奇怪的问题,就是Url中,如果将中文字符作为参数值传递时,QueryString得到的值可能会出错。简单的说,比如下面这个Url:
UrlParmTest.aspx?parm1=中国&parm2=中国人
在Request.QueryString时,parm1和parm2得到都是”中国”,显然出现了问题,可是在某些情况下却是正常的。

如果请求不是直接通过URL,而使用Response.Redirect在服务器端操作,没有遇到过类似的问题。

当时我想中文是双字节编码,可能传递的时候就是有不确定性,还是用英文好。

可是为什么在Server端Redirect就是正常的,问题在哪里呢?


如果在.cs文件中设置中文参数,请在中文参数外使用Server.UrlEncode(“中文”)对中文进行Encode
如果在.aspx文件中设置,请使用<%=Server.UrlEncode(“中文”)%>进行Encode
在QueryString时,不用再进行Decode,可以获得正常的中文字符串

下面是给出的一些解释:
UrlEncode把一些多字节字符转换成url里允许的单字节字符,本来浏览器就会自动做的,但是目前确实存在一些问题,所以自己再Encode一下,在接受端会自动对Url进行Decode。

我想Response.Redirect可能可以确保作Encode的工作,所以没有问题。

JavaScript Base64编码和解码,实现URL参数传递

为什么需要对参数进行编码?相信有过开发的经验的广大程序员都知道,在Web中,若是直接在Url地址上传递参数值,若是中文,或者+等什么的就会出现乱码现象,若是数字或者英文的好象没有什么问题,简言之,传递过来的参数是需要进行编码的。
在这里,也许有人会说,为什么不直接用Server.UrlDecode和Server.UrlEncode这两个来进行编码和解码的操作呢?

的确,这两个服务器端对象很好使用,用起来也很方便,但是,若在客户端是HTML的Input,查询的时候页面是HTML或者其他的,反正不是.NET的,那这个对象还可以用吗?


我现在就遇到这样的问题,查询的东东放在页面,而且那个页面我根本不想让他是.aspx结尾的,哈,感觉HTML的挺不错,而且里面的控件也是用HTML对象的。

下面先来看两个函数,UTF16转UTF8和UTF8转Utf16的。
function utf16to8(str)
{
var
out, i, len, c;

out = “”;
len
= str.length;
for(i = 0; i < len; i++) {
c
= str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
}
else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}

}

return out;
}


function utf8to16(str)
{
var
out, i, len, c;
var char2, char3;

out = “”;
len
= str.length;
i
= 0;
while(i < len) {
c
= str.charCodeAt(i++);
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += str.charAt(i1);
break;
case 12: case 13:
// 110x xxxx   10xx xxxx
char2 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx  10xx xxxx  10xx xxxx
char2 = str.charCodeAt(i++);
char3
= str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2
& 0x3F) << 6) |
((char3
& 0x3F) << 0));
break;
}

}


return out;
}


那么为什么需要进行转化呢?因为在JavaScript中获得的中文字符是用UTF16进行编码的,和我们统一的页面标准格式UTF
8可不一样哦,所以需要先进行转化,上面的函数UTF16到UTF8,然后再进行Base64的编码。

下面是关于Js进行Base64编码和解码的相关操作:

var base64EncodeChars
= ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/;
var base64DecodeChars
= new Array(
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 1, 1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 1, 1, 1, 1, 1, 1,
1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 1, 1, 1, 1, 1,
1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 1, 1, 1, 1, 1);
//客户端Base64编码
function base64encode(str) {
var
out, i, len;
var c1, c2, c3;

len
= str.length;
i
= 0;
out = “”;
while(i < len) {
c1
= str.charCodeAt(i++) & 0xff;
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += ==;
break;
}

c2
= str.charCodeAt(i++);
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += =;
break;
}

c3
= str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
out += base64EncodeChars.charAt(c3 & 0x3F);
}

return out;
}

//客户端Base64解码
function base64decode(str) {
var c1, c2, c3, c4;
var i, len,
out;

len
= str.length;
i
= 0;
out = “”;
while(i < len) {
/* c1 */
do {
c1
= base64DecodeChars[str.charCodeAt(i++) & 0xff];
}
while(i < len && c1 == 1);
if(c1 == 1)
break;

/* c2 */
do {
c2
= base64DecodeChars[str.charCodeAt(i++) & 0xff];
}
while(i < len && c2 == 1);
if(c2 == 1)
break;

out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

/* c3 */
do {
c3
= str.charCodeAt(i++) & 0xff;
if(c3 == 61)
return out;
c3
= base64DecodeChars[c3];
}
while(i < len && c3 == 1);
if(c3 == 1)
break;

out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

/* c4 */
do {
c4
= str.charCodeAt(i++) & 0xff;
if(c4 == 61)
return out;
c4
= base64DecodeChars[c4];
}
while(i < len && c4 == 1);
if(c4 == 1)
break;
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
}

return out;
}


这样传递过去的值就可以在服务器端解码操作了。
下面是C#的Base64加码和解码的相关类:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace CNVP.Base64
{
/// <summary>
/// MyBase64 的摘要说明
/// </summary>

public class MyBase64
{
public MyBase64()
{
//
// TODO: 在此处添加构造函数逻辑
//
}

/// <summary>
/// 服务器端Base64编码
/// </summary>
/// <param name=”data”></param>
/// <returns></returns>

public string base64Encode(string data)
{
try
{
byte[] encData_byte = new byte[data.Length];
encData_byte
= System.Text.Encoding.UTF8.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}

catch (Exception e)
{
throw new Exception(Error in base64Encode + e.Message);
}

}

/// <summary>
/// 服务器端Base64解码
/// </summary>
/// <param name=”data”></param>
/// <returns></returns>

public string base64Decode(string data)
{
try
{
System.Text.UTF8Encoding encoder
= new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode
= encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(data);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte,
0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}

catch (Exception e)
{
throw new Exception(Error in base64Decode + e.Message);
}

}

}

}


var Keyword
=base64encode(utf16to8(document.all.Keyword.value));
Keyword
=Keyword.replace(+,%2B);//替换+,否则在服务器解码的时候会出错
服务器端使用以下代码调用:
CNVP.Base64.MyBase64 base64
= new CNVP.Base64.MyBase64();
Keyword
=base64.base64Decode(Keyword);


赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏