Skip to content

Instantly share code, notes, and snippets.

@lukaszkorecki
Created June 21, 2011 17:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukaszkorecki/1038408 to your computer and use it in GitHub Desktop.
Save lukaszkorecki/1038408 to your computer and use it in GitHub Desktop.
How to upload files using JSOAuth and FormData

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)

<!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>
@ChrisRM
Copy link

ChrisRM commented Jun 24, 2011

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

@lukaszkorecki
Copy link
Author

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.

@chadtatro
Copy link

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 )

@lukaszkorecki
Copy link
Author

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

@adrian3
Copy link

adrian3 commented Aug 30, 2011

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.

@lukaszkorecki
Copy link
Author

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.

@adrian3
Copy link

adrian3 commented Aug 31, 2011

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

@lukaszkorecki
Copy link
Author

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.

@adrian3
Copy link

adrian3 commented Aug 31, 2011

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);

@lukaszkorecki
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment