`
8821249
  • 浏览: 68745 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

豆瓣开放平台api的坑

阅读更多
最近在接豆瓣的分享,期间碰到了较多的陷阱,一路磕磕碰碰,还好最终都解决了。下面总结下期间耗费了我一天的一个巨坑。。。

第一次使用在使用豆瓣广播api(shuo/v2/statuses/)即碰壁,查找原因后发现最后的“/”必不可少。

那么我们继续:

MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(httpConnectionManager); 
PostMethod postMethod = new PostMethod("https://api.douban.com/shuo/v2/statuses/");
Part[] parts = new Part[2];
parts[0] = new StringPart("source","XXXXXXXXX", "UTF-8");
parts[0] = new StringPart("text", "ttttt", "UTF-8");
			
File file = new File("D:\\upload.jpg");
FilePart filePart = new FilePart("image", file.getName(), file,new MimetypesFileTypeMap().getContentType(file), "UTF-8");
parts[1] = filePart;

MultipartRequestEntity requestEntity = new MultipartRequestEntity(parts, postMethod.getParams());
postMethod.setRequestEntity(requestEntity);
postMethod.setRequestHeader("Authorization", "Bearer XXXXXX");
int statusCode = client.executeMethod(postMethod);

String response = new String(postMethod.getResponseBody(), "UTF-8");
System.out.println("response--->" + response);
System.out.println("statusCode--->" + statusCode);

我用的是httpclient3.1,返回结果为{"msg":"不支持的图片格式","r":0}

怎么办?检查多次代码,尝试调整编码多次后,依旧,宣告失败,上豆瓣api小组上搜索,满眼尽是提问的,官方的回复也很简单:"我们的api没问题,请检查参数Content-Type"。

好吧我怕你了,既然你说你们的api没问题,我拿你们提供的sdk参考下总可以吧。于是下载sdk,我x,老版本的。attachments方式的,不支持image参数。

灵光一显,没准豆瓣自己官方的android里可以用一定的借鉴意义,反编译之,上应用汇下载豆瓣广播,使用apk2java解压,jdgui反编译之。
发现android客户端里使用的是httpclient4。参数设置可我也没什么不同。

使用httpclient4写了一个demo,果然可以发送成功。
	public static void main(String[] args) throws FileNotFoundException, IOException {
		
		MultipartEntity localMultipartEntity = new MultipartEntity();
	    localMultipartEntity.addPart("text", new StringBody("texttexttext", Charset.forName("UTF-8")));
	    
	    File file = new File("D:\\upload.jpg");
	    localMultipartEntity.addPart("image", new ByteArrayBody(IOUtils.toByteArray(new FileInputStream(file)), 
	    		"image/jpeg", "upload.jpg"));
	    
	    HttpClient httpClient = new DefaultHttpClient();
	    
	    HttpParams params = httpClient.getParams(); // 计算网络超时用
	    
	    HttpConnectionParams.setConnectionTimeout(params, 5 * 1000);
	    HttpConnectionParams.setSoTimeout(params, 2 * 1000);
	    
	    HttpPost request = new HttpPost("http://api.douban.com/shuo/v2/statuses/");
	    request.addHeader("Authorization", "Bearer XXXXXX");
	    request.setEntity(localMultipartEntity);
	    HttpResponse response = httpClient.execute(request); 
	    System.out.println(response.getStatusLine());
	    response.getEntity().writeTo(System.out);
	}
	
	static class ByteArrayBody extends AbstractContentBody {
		private final byte[] data;
		private final String filename;

		public ByteArrayBody(byte[] paramArrayOfByte, String paramString) {
			this(paramArrayOfByte, "application/octet-stream", paramString);
		}

		public ByteArrayBody(byte[] paramArrayOfByte, String paramString1,
				String paramString2) {
			super(paramString1);
			if (paramArrayOfByte == null)
				throw new IllegalArgumentException("byte[] may not be null");
			this.data = paramArrayOfByte;
			this.filename = paramString2;
		}

		public String getCharset() {
			return null;
		}

		public long getContentLength() {
			return this.data.length;
		}

		public String getFilename() {
			return this.filename;
		}

		public String getTransferEncoding() {
			return "binary";
		}

		public void writeTo(OutputStream paramOutputStream) throws IOException {
			paramOutputStream.write(this.data);
		}
	}

如意料,httpclient4正常,ok,有了样本,那就离胜利不远了。开始分析。。。。
下载fiddler抓包,由于fiddler无法对java的应用抓包,需要额外设置下,分别对以上两个应用设置代理。
这里豆瓣使用的协议为https,需要进行认证,虽然可以通过注册一个自己的EasySSLProtocolSocketFactory跳过认证,但我们只是为了看下request报文的body,没必要捣鼓这些,将请求地址中的https改为http即可。
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost("127.0.0.1", 8888));  //httpclient4
client.getHostConfiguration().setProxy("127.0.0.1", 8888); //httpclient3


抓包获得的boundary如下:
httpclient3抓到的内容:
------------------314159265358979323846
Content-Disposition: form-data; name="image"; filename="upload.jpg"
Content-Type: image/jpeg; charset=UTF-8
Content-Transfer-Encoding: binary

XXXXXXX图片bytesXXXXXXX

httpclient4抓到的内容:
--Ih2sX8QV86yWiK_Mux82mBVKkDLWVxG4
Content-Disposition: form-data; name="image"; filename="upload.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary

XXXXXXX图片bytesXXXXXXX


可以看出来唯一的区别在于4比3少了一个“charset=UTF-8”,重写httpclient3的boundary输出,发表成功。。
看来是豆瓣接收上传的图片时没有完全按http1.1协议来。摔~~~~~~

重写httpclient3的boundary输出的方法,自定义一个自己的FilePart:
	public class DoubanFileBase extends FilePart {
	    
		public MyFileBase(String name, String fileName, File file,
				String contentType, String charset)
				throws FileNotFoundException {
			super(name, fileName, file, contentType, charset);
		}
		
		protected void sendContentTypeHeader(OutputStream out)
				throws IOException {
			String contentType = getContentType();
			if (contentType != null) {
				out.write(CRLF_BYTES);
				out.write(CONTENT_TYPE_BYTES);
				out.write(EncodingUtil.getAsciiBytes(contentType));
			}
		}
	}
分享到:
评论
2 楼 mengxinyu5490 2014-05-05  
谢谢你的文章,这个问题困扰了很长时间了
1 楼 alexyu_yxj 2013-02-21  
确实一个巨大的坑!我也弄了两个晚上,感谢有你的文章!!

相关推荐

    java 豆瓣网API

    1. **认证机制**:为了确保安全和防止滥用,豆瓣API通常需要开发者进行身份验证。Java豆瓣网API可能包含OAuth认证流程,开发者需要申请API密钥,并在请求时携带这些凭证,以获得访问权限。 2. **资源和URL**:豆瓣...

    微信小程序demo:豆瓣电影:使用API(源代码+截图)

    微信小程序demo:豆瓣电影:使用API(源代码+截图)微信小程序demo:豆瓣电影:使用API(源代码+截图)微信小程序demo:豆瓣电影:使用API(源代码+截图)微信小程序demo:豆瓣电影:使用API(源代码+截图)微信小程序demo:...

    豆瓣网APi应用

    1. **豆瓣API**:豆瓣API是豆瓣开放给开发者的数据接口,它允许开发者通过HTTP协议访问豆瓣平台上的各类数据,如用户信息、书籍、电影、音乐等,用于创建个性化应用或增强已有应用的功能。 2. **API密钥**:使用...

    豆瓣api测试 豆瓣api测试

    豆瓣API是豆瓣平台提供的一种服务,允许开发者通过编程方式获取豆瓣网站上的各种数据,如电影、书籍、音乐等资源的信息,用户评论,评分等。这篇内容将深入探讨豆瓣API的测试及其重要性。 首先,我们来理解什么是...

    豆瓣api实践项目

    豆瓣API,全称为Douban API,是豆瓣网对外开放的一系列接口,允许开发者通过这些接口获取到豆瓣平台上的各种数据,如图书、电影、音乐等资源的信息,以便进行二次开发和创新应用。在这个基于豆瓣API的Android实践...

    豆瓣API实现客户端源码

    豆瓣API实现客户端源码是一个基于Android平台的项目,旨在帮助开发者了解如何利用豆瓣开放的API来构建一个功能丰富的客户端应用。这个源码实例涵盖了多个关键知识点,包括用户授权、数据获取、界面展示以及搜索功能...

    豆瓣API获取书籍详细信息

    豆瓣API是一种公开的接口,允许开发者通过特定的请求方式获取豆瓣平台上的各种资源信息,包括电影、音乐、书籍等。在这个场景中,我们将重点关注如何利用豆瓣API获取书籍的详细信息。首先,我们需要理解API...

    豆瓣读书v2API访问小程序(python).pdf

    豆瓣读书v2API访问小程序(python) 摘要: 本文介绍了使用 Python 语言开发的豆瓣读书 v2 API 访问小程序。该小程序使用 WxPython 开发工具,实现了 GUI 程序,并使用 GitHub 网站提供的代码托管服务管理源代码。小...

    豆瓣API接口获取书籍详细信息C#

    豆瓣API是豆瓣网提供的一套服务,让开发者可以获取到豆瓣平台上的各种数据,如书籍、电影、音乐等的信息。本项目重点是利用豆瓣API来获取书籍的详细信息,通过输入ISBN(国际标准书号)来实现这一功能,而开发语言...

    一个基于豆瓣API的书架借阅平台

    在这个基于豆瓣API的书架借阅平台项目中,主要使用了Vue2、Element UI和ES2015等技术栈。下面将详细介绍这些技术及其在项目中的应用。 **Vue2** 是一个轻量级的前端JavaScript框架,由尤雨溪开发,其核心理念是通过...

    豆瓣新API Java SDK 调用

    豆瓣API Java SDK调用是Java开发者与豆瓣服务交互的重要工具,尤其对于想要集成豆瓣功能到自己的应用程序中的开发者来说,这是一个必不可少的资源。豆瓣API提供了包括但不限于书籍、电影、音乐等多方面的信息获取和...

    vue版豆瓣图书api搜索

    你可以通过模拟数据或者使用其他开放的API来替换豆瓣API,例如Open Library或Goodreads API,这样依然可以实践前端数据获取和展示的过程。同时,这个项目也可以引导我们学习如何处理API调用的错误,如超时、无响应等...

    微信小程序demo:豆瓣电影:使用API53.zip

    关于豆瓣API,它是豆瓣开放给开发者使用的接口,提供了电影、图书、音乐等各类信息的查询服务。在本项目中,开发者可能使用了API53(可能代表特定版本或者接口编号)来获取电影的列表、详情等数据。通常,调用API会...

    豆瓣API php应用

    描述中的重复内容“豆瓣API php应用”进一步强调了这一主题,表明重点是围绕PHP编程环境下如何对接豆瓣的开放接口。 **知识点详解** 1. **豆瓣API介绍**: 豆瓣API(Application Programming Interface)是豆瓣提供...

    豆瓣API获取书籍详细信息(Java代码)

    豆瓣API是豆瓣网提供的一种服务,允许开发者通过特定的请求方式获取豆瓣平台上的数据,例如书籍、电影、音乐等资源的信息。在这个场景中,我们将关注如何使用Java语言来调用豆瓣API,获取特定书籍的详细信息。 首先...

    通过Python爬虫自建豆瓣电影API.zip

    在开发微信小程序「影库MDb」时,使用了豆瓣api来获取电影信息,后来由于豆瓣apikey失效了,小程序就无法正常访问,而个人主体貌似无法申请官方apikey,所以自己抽时间通过爬虫的方式写了个电影接口。这里把项目中的...

    使用豆瓣api查找本地电影评分来决定看什么电影

    豆瓣API是开发者可以用来访问其平台上各种资源(如电影、书籍、音乐等)的数据接口。 首先,我们需要理解什么是API。API(Application Programming Interface)是软件之间交互的一种方式,它定义了不同应用如何相互...

    python根据豆瓣电影API批量修改视频文件名

    豆瓣是一个提供电影、书籍、音乐等评分和评论的平台,它开放了一部分API供开发者使用。通过这个API,我们可以获取到电影的信息,如电影名称、导演、演员、评分等。在本案例中,我们将重点利用电影名称这一信息。 要...

    根据豆瓣电影API,写的微信小程序 (已不可用)

    1. **源代码文件**:小程序的前端和后端代码,前端主要负责用户界面展示和交互,后端负责与豆瓣API的交互,获取和处理数据。 2. **配置文件**:小程序的配置信息,包括项目设置、网络请求配置、微信小程序的appid等...

Global site tag (gtag.js) - Google Analytics