Tuesday, March 24, 2015

Making Twitter Media Upload Api work with Java

I was trying to upload an image and do status update on twitter using there api version 1.1.
For this I was using media/upload.json . I was trying to send content of files as base64 encoded string and setting the appropriate content-type and content-transfer-encoding. But this didn't work.
I was getting errors like:

1) Missing paramter media
2) Could not authenticate.

My main reason to use this approach was I was getting image url and didn't wanted to save it into a file.

But this never worked, then I took a different approach of saving the imageurl into a file and doing a multi part upload. Code for it is below. Hope this helps someone.


private String uploadImage(String imageUrl)
{
File f = new File("/tmp/twitterUploadImage_"+StringUtil.encodeURL(imageUrl));
try
{
FileUtils.copyURLToFile(new URL(imageUrl), f);
}
catch (IOException e)
{
logger.severe("Failed to save image in a file");
return null;
}
UrlReader.FetchResponse resp = post(TWITTER_UPLOAD_URL + "media/upload.json", f, "media", true);
if (resp == null || StringUtil.isEmpty(resp.body)) return null;
try
{
logger.severe(resp.body);
JSONObject obj = new JSONObject(resp.body);
if (obj.has("media_id_string"))
{
return obj.getString("media_id_string");
}
else
{
logger.severe("Media Id not found "+ resp.body);
}
}
catch (JSONException jse)
{
logger.severe("JSON exception "+ resp.body);
}
return null;
}

public UrlReader.FetchResponse post(String url, File file, String paramName, boolean personaSpecific) //Not changing SocialAuthorization rightaway.
{
Persona person = this.loadPersona(index, personaSpecific);
if(person == null)
return null;
Token accessToken = new Token(person.getToken(), person.getKey());
OAuthRequest req = new OAuthRequest(Verb.POST, url);
OAUTHSERVICE.signRequest(accessToken, req);
HttpEntity entity = createMultipartEntity(file, paramName);
UrlReader.FetchResponse response = UrlReader.HttpPost(url, req.getHeaders(), entity);
return response;
}

private HttpEntity createMultipartEntity(File f, String paramName)
{
MultipartEntityBuilder builder = MultipartEntityBuilder.create();      
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
FileBody fileBody = new FileBody(f); //image should be a String
builder.addPart(paramName, fileBody);
HttpEntity entity = builder.build();
return entity;
}