HttpURLConnection响应head内容的编码方式,如何正确识别,100分在线等

JavaLover00000 2013-11-04 11:18:11
我用HttpUrlConnection 连接下载一个mp3
地址如下:
http://zhangmenshiting.baidu.com/data2/music/91731224/91731224.mp3?xcode=35364211a9bc8d289ad59150fa1ad1eb5dc4eabdf6e0aebb
返回的 response head中可以读取到文件名字
如下:
Content-Disposition:attachment; filename="²»ÖµµÃ.mp3"
现在我的需求是,正确识别这个filename的编码方式
这是个汉字名字,我用 new String(str.getBytes("iso-8859-1"),"gbk");
能正确的到名字,但是我希望能不是由我代码写死的来转成gbk,而是有代码或者其他方式动态识别出来

注:用浏览器访问这个地址,是可以获得正确的文件名的,指定浏览器编码方式并不会导致乱码,希望有经验的或者做过浏览器的指点指点,浏览器是如何做到的

下面是完整测试代码,拷贝即可运行:
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;


public class T1 {
public static void main(String[] args) throws UnsupportedEncodingException, Throwable {
String downloadUrl = "http://zhangmenshiting.baidu.com/data2/music/91731224/91731224.mp3?xcode=35364211a9bc8d289ad59150fa1ad1eb5dc4eabdf6e0aebb";
URL url = new URL(downloadUrl);
// 打开HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置 HttpURLConnection的断开时间
conn.setConnectTimeout(5000);
// 设置 HttpURLConnection的请求方式
conn.setRequestMethod("GET");
// 设置 HttpURLConnection的接收的文件类型
conn.setRequestProperty(
"Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
+ "application/x-shockwave-flash, application/xaml+xml, "
+ "application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, "
+ "application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
// 设置 HttpURLConnection的接收语音
conn.setRequestProperty("Accept-Language", Locale.getDefault().toString());
// 指定请求uri的源资源地址
conn.setRequestProperty("Referer", downloadUrl);
// 设置 HttpURLConnection的字符编码
conn.setRequestProperty("Accept-Charset", "UTF-8");
// 检查浏览页面的访问者在用什么操作系统(包括版本号)浏览器(包括版本号)和用户个人偏好
// conn.setRequestProperty(
// "User-Agent",
// "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2;"
// + " Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; "
// + ".NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152;"
// + " .NET CLR 3.5.30729)");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36");
conn.setRequestProperty("Connection", "Keep-Alive");

conn.connect();

printResponseHeader(conn);
}

private static void printResponseHeader(HttpURLConnection http) throws UnsupportedEncodingException {
Map<String, String> header = getHttpResponseHeader(http);
for (Map.Entry<String, String> entry : header.entrySet()) {
String key = entry.getKey() != null ? entry.getKey() + ":" : "";
System.out.println(key + entry.getValue());
}
}

private static Map<String, String> getHttpResponseHeader(
HttpURLConnection http) throws UnsupportedEncodingException {
Map<String, String> header = new LinkedHashMap<String, String>();
for (int i = 0;; i++) {
String mine = http.getHeaderField(i);
if (mine == null)
break;
header.put(http.getHeaderFieldKey(i), mine);
}
return header;
}
}


下面是我的运行结果:
HTTP/1.1 200 OK
Server:JSP2/1.0.16
Date:Mon, 04 Nov 2013 03:06:26 GMT
Content-Type:audio/mpeg
Connection:close
Content-Length:2518244
Accept-Ranges:bytes
Last-Modified:Wed, 23 Oct 2013 02:56:23 GMT
Expires:Fri, 22 Nov 2013 12:20:18 GMT
x-bs-version:9AB3778C345E22493B1B8D3D1E7D92C1
ETag:f05c8c3e7e7328b5ec3913051c256170
x-bs-request-id:MTAuNDYuMjI4LjQ0OjgwODA6Mjk3MDIxMTc1NToyMy9PY3QvMjAxMyAyMDoyMDoxOCA=
Content-Disposition:attachment; filename="²»ÖµµÃ.mp3"
x-bs-meta-crc32:657750654
Content-MD5:f05c8c3e7e7328b5ec3913051c256170
x-bs-client-ip:NTguMjE1LjEyMy45Mg==
x-bs-uncopyable:enable
Cache-Control:max-age=2592000

...全文
31771 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
String encode = "GB2312"; try { if (str.equals(new String(str.getBytes(encode), encode))) { // 判断是不是GB2312 String s = encode; return s; // 是的话,返回“GB2312“,以下代码同理 } } catch (Exception exception) { } encode = "ISO-8859-1"; try { if (str.equals(new String(str.getBytes(encode), encode))) { // 判断是不是ISO-8859-1 String s1 = encode; return s1; } } catch (Exception exception1) { } encode = "UTF-8"; try { if (str.equals(new String(str.getBytes(encode), encode))) { // 判断是不是UTF-8 String s2 = encode; return s2; } } catch (Exception exception2) { } encode = "GBK"; try { if (str.equals(new String(str.getBytes(encode), encode))) { // 判断是不是GBK String s3 = encode; return s3; } } catch (Exception exception3) { } return ""; // 如果都不是,说明输入的内容不属于常见的编码格式
  • 打赏
  • 举报
回复
貌似filename是固定“iso-8859-1”字符集的
JavaLover00000 2013-11-11
  • 打赏
  • 举报
回复
唉,看来没办法了,这周结贴~
JavaLover00000 2013-11-07
  • 打赏
  • 举报
回复
用linux下浏览器测试了下,下载保存的文件名是乱码 看来无解了。。
JavaLover00000 2013-11-06
  • 打赏
  • 举报
回复
上面的url已经不能访问了,我找了个新的,还是百度音乐 http://zhangmenshiting.baidu.com/data2/music/90350586/8930817375600128.mp3?xcode=04132d53ea78dd59a64b8fb1613361b824b7b177cb0d29e2
jdgdf566 2013-11-05
  • 打赏
  • 举报
回复
浏览器的很多东西都是只支持utf-8,例如网址、ajax,只不过很多位于两端的软件能够自动处理而已。header部分也是ansii或utf-8的。 中文版windows操作系统的字符集是gbk(其实也不是gbk,而是微软自己捣鼓的chinese-ms936/chinese-ms950,但是几乎等于gbk)。百度没有转成utf-8,可能就是考虑到这一点。这可能可以解释为什么浏览器可以识别。百度的东西都是经过测试的。同时,也不高深。
JavaLover00000 2013-11-05
  • 打赏
  • 举报
回复
顶一下,有木有好的解决方法
JavaLover00000 2013-11-05
  • 打赏
  • 举报
回复
filename="²»ÖµµÃ.mp3" 像这么一段文字 如果能识别出来是什么编码的 那最好不过了,8楼说的ICU4J 应该就是做这个事情的吧
JavaLover00000 2013-11-05
  • 打赏
  • 举报
回复
ICU4J 要引入一个蛮大的jar,不太好,我的是android程序
有巢鱼 2013-11-04
  • 打赏
  • 举报
回复
试试看CharsetDetector(ICU4J),应该可以满足你的要求。
JavaLover00000 2013-11-04
  • 打赏
  • 举报
回复
我觉得,流中的编码与Content-Disposition内容的编码应该没有直接关系吧
JavaLover00000 2013-11-04
  • 打赏
  • 举报
回复
引用 5 楼 huxiweng 的回复:
1、urlconn.getContentType来获取,如果没有charset,则执行2 2、解析html页面,获取<meta>标签的contentType,如果还没有有charset,则默认 即:获取的byte[]直接new String,不加任何编码! 还有试试获取这个流的编码:

private static String getEncode(InputStream inputStream){
		String code = "gb2312";
		try {
			byte[] head = new byte[3];
			inputStream.read(head);
			if (head[0] == -17 && head[1] == -69 && head[2] == -65)
				code = "UTF-8";
			if (head[0] == -1 && head[1] == -2)
				code = "UTF-16";
			if (head[0] == -2 && head[1] == -1)
				code = "Unicode";

			inputStream.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return code;
	}
我请求的这个地址是百度音乐的地址,他的页面编码是utf-8 content-type中也没有编码方式 但Content-Disposition中的内容却是gbk的,我用 new String(str.getBytes("iso-8859-1"),"gbk")能得到正确的名字 不知道浏览器是如何识别出来的, 目前只能暂时 只用 utf-8 转一下码,出来的是乱码 有考虑 做个白名单,但是这样就不完美了,如果能有办法正确识别出来最好了, 你这个读取流的编码,这种方式我来研究研究
teemai 2013-11-04
  • 打赏
  • 举报
回复
1、urlconn.getContentType来获取,如果没有charset,则执行2 2、解析html页面,获取<meta>标签的contentType,如果还没有有charset,则默认 即:获取的byte[]直接new String,不加任何编码! 还有试试获取这个流的编码:

private static String getEncode(InputStream inputStream){
		String code = "gb2312";
		try {
			byte[] head = new byte[3];
			inputStream.read(head);
			if (head[0] == -17 && head[1] == -69 && head[2] == -65)
				code = "UTF-8";
			if (head[0] == -1 && head[1] == -2)
				code = "UTF-16";
			if (head[0] == -2 && head[1] == -1)
				code = "Unicode";

			inputStream.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return code;
	}
  • 打赏
  • 举报
回复
引用 3 楼 JavaLover00000 的回复:
[quote=引用 2 楼 ghostkngiht 的回复:] 这个一般只有汉字会产生乱码,所以直接写gbk应该就行了。不清楚怎么判断乱码使用的编码。
直接用gbk不太好吧,如果遇上其他国家语言的,比如日文,韩文,xx文什么的,那不就悲剧了 [/quote] utf-8 吧
JavaLover00000 2013-11-04
  • 打赏
  • 举报
回复
引用 2 楼 ghostkngiht 的回复:
这个一般只有汉字会产生乱码,所以直接写gbk应该就行了。不清楚怎么判断乱码使用的编码。
直接用gbk不太好吧,如果遇上其他国家语言的,比如日文,韩文,xx文什么的,那不就悲剧了
ghostkngiht 2013-11-04
  • 打赏
  • 举报
回复
这个一般只有汉字会产生乱码,所以直接写gbk应该就行了。不清楚怎么判断乱码使用的编码。
JavaLover00000 2013-11-04
  • 打赏
  • 举报
回复
没人遇到类似的问题么?

81,122

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧