public
Created

How to upload files using JSOAuth and FormData

  • Download Gist
Readme.markdown
Markdown

Compatibility

Works in Mikrob which is deployed both to Titanium Desktop and as a Chrome Application.

This code was extracted from my own code and a wrapper library which I'm working on.

Any questions? Post them in comments.

Behind the scenes

Here's where everything happens:

  • jsOAuth goes through your post data and checks whether a reference to a file was included source

  • if it finds one, it resets the conent-type source

  • and build the whole form data object for you source

Notes

Few things to keep in mind:

  • I used it only with an API which doesn't use OAuth-echo, and allows direct uploads

  • this is based on OAuth 1.0a (Oauth2 is not supported yet)

oauth-file-upload.html
HTML
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 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 52 53 54 55
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>OAuth form data test</title>
<script src="zepto.js" type="text/javascript" charset="utf-8"></script>
<script src="jsoauth.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
// I'm assuming that your user is already authenticated and can make requests etc
var oauth = Oauth(options = {});
 
 
function oauthUpload() {
var body = $('#status').value(),
// this is the important bit:
// you need to get the raw dom element which is the file upload filed in your form
file = $('#picture').dom[0].files[0],
 
// your usual callbacks
callbacks = {
onSuccess : function() {
console.log('upload worked!')
},
onFailure : function() {
console.log('upload failed!');
console.dir(arguments);
}
},
 
uploadData = {
'status' : body,
'file' : file
};
 
oauth.post('http://example.com/api/picture_upload',uploadData, callbacks.onSuccess, callbacks.onFailure);
 
return false;
}
 
$('#mainForm').submit(oauthUpload)
</script>
 
</head>
<body >
<div id="form">
<form id="mainForm" action="/" method="post" accept-charset="utf-8">
 
<input type="file" name="picture" value="value" id="picture"/>
<input type="text" name="status" value="value" id="status"/>
 
<p><input type="submit" value="Continue &rarr;"/></p>
</form>
</div>
</body>
</html>

Now how do you get to show the file you uploaded using jsoauth ?

Depends on the API you're working with.

The one I'm using simply gives me a JSON response with an url to the image.

I tried to make this work with OAuth Echo for TwitPic with no luck.

When I attempted to upload a photo I'd get 401 Unauthorized. After looking at the actual post data I didn't see any of the oauth variables posted. I believe this is what was causing TwitPic to reject it.

(This was tested using the BlackBerry WebWorks SDK on the PlayBook: https://github.com/blackberry/WebWorks/wiki )

Right.

As the readme says - I didn't use JSOauth with Echo mechanism, so I can't be much of a help at this point, however - Spazcore has code which deals with Twitpic upload (and few other services).

You might want to take a look at that

I am trying to get this to work in an iPhone app and am wondering if you have any recommendations for replacing the "input type="file"" part of the code since that isn't supported on an iPhone. If I have a base64 string of an image could I feed that to the uploader? How would I go about doing that? Thanks in advance for your advice, lukaszkorecki.

In theory you could use my example and change this line:

 file = $('#picture').dom[0].files[0],

to

file = imageDataToB64(whatever)

jsOAuth works out whether the data you're uploading is a string or a file field (as it can be seen here). Probably you will have to override the Content-Type header.

Thanks, Ɓukasz. Is changing the Content-Type done in my javascript or do I overwrite something in jsOAuth-1.3.1.min.js?

I assume it should work out of the box (assuming that the API you're interacting with expects that the image data is going to be B64'enc'd), since you're sending plain text.

Let me know if it works (and which API you're working with) - if it's ok we will add it to jsOAuth docs/examples.

I am working with the Twitter API. I was able to get this working in php using the php library tmhOAuth.php. For that I have to base64_decode my image data before I post it. The same thing didn't work in javascript, though. Maybe I am decoding it wrong or something. Right now it looks like this:
file = $.base64Decode(mydata);

I just skimmed through Twitter's API docs, and found this example - as you can see it's uploading the file directly, using multipart content type.

I can't find an example which uses B64 encoded data though.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.