4

I have a nodejs (+express + mongodb,gridstore) backend, and want to upload a photo to a facebook album.

I came across 2 methods. the first ( https://developers.facebook.com/blog/post/526/ ) needs to get the full url resource of my picture, which I don't have as it is data that I pull from gridstore, and the second ( https://developers.facebook.com/docs/reference/api/album/ ) is very poorly documented, via the Graph API, where I can't figure out what my request should look like. (the form-data, what fields should it have, how to convert my data blob\stream from gridstore to it)

Here is what I currently have, and doesn't work:

facebook.uploadPhoto = function (token, albumId, photo, callback) {
    var fb = fermata.json('https://graph.facebook.com/' + albumId);
    fb.photos({access_token:token}).post({'Content-Type':"multipart/form-data"}, {source:{data:photo}}, callback);
};

Any help would be much appreciated

Nadav
  • 1,167
  • 2
  • 19
  • 43
  • I’d suggest you start by Googling, what `multipart/form-data` actually means. And researching other questions might also help, this one for example: http://stackoverflow.com/questions/7945949/node-js-generate-multipart-form-data – CBroe Sep 29 '12 at 16:54
  • @CBroe Thanks, but I have read all there is to read online, and am already using fermata as the SO question suggested (In which I came across in my tries to upload a photo). I'll update my question to clarify that... I'm probably missing something very simple. – Nadav Sep 30 '12 at 07:44
  • Isn't it easier to create urls for the images and use the first method? If you can get the images from gridstore using your application you should also be able to create unique urls for those images. – Tiddo Oct 01 '12 at 17:14
  • I tried going that path, but couldn't find a way to construct the full url (without hardcoding my domain in there) – Nadav Oct 01 '12 at 22:55
  • http://stackoverflow.com/questions/7507015/node-js-get-server-hostname-of-current-process – CBroe Oct 02 '12 at 12:36
  • What's not working about this? You give no idea as to the response from the API? – Sammaye Oct 03 '12 at 14:30

3 Answers3

4

There is a good chance the file is not properly serialized. Fermata will take a node File buffer via data. Have you tried passing that instead?

fs.readFile("/path/to/photo.jpg", function (err, data) {
  fermata.json("https://graph.facebook.com/graph/api").post({"Content-Type":"multipart/form-data"},  {fileField:  {data:data, name:"", type:""}  }, callback);
});

Adding your access token etc..

Scott
  • 1,012
  • 7
  • 14
  • This seems likely to me, too. In the current version if the data is not already a Buffer, Fermata will coerce it to one by way of a string. – natevw Jan 16 '13 at 19:12
1

I solved this problem by using a simple POST to the facebook graph API using the poster module.

var options = {
  uploadUrl: 'https://graph.facebook.com/'+user+'/photos?access_token='+accessToken,
  method: 'POST',
  fileId: 'source',
  fields: {'message':''} // Additional fields according to graph API
};

var fileName = ''; // Local or remote url where to find the image
poster.post(fileName, options, function(err, data) {
  if (err) {
    //Something went wrong
  } else {
    // Everything ok
  }
});
DeadAlready
  • 2,988
  • 19
  • 18
  • Thanks, but as I mentioned earlier, I do not have a path to a file, as this is data coming from a DB (MongoDB's GridStore) – Nadav Oct 05 '12 at 08:52
  • I tried this and it doesn't work... oh, and there's a but in poster where it doesn't submit https requests but even after i fixed it, facebook still returns error 400 – Nadav Oct 07 '12 at 08:40
0

Honestly, I've got limited experience working with the Facebook graph API and mostly using PHP and Java.

Here is some streams that you might find helpful:

Basically, I recommend you punt a little in your implementation and code it in the following way:

  1. Create a REST web service function call in Node.js to output a single image from gridstore using an internal UID.
  2. Code your uploadToFacebook function to use an image URL that calls the REST web service function.

Basically, this would allow you to validate the image output by pointing your browser to the REST web service and avoid any blob\stream conversions inside your uploadToFacebook function. I'm assuming you store the image in gridstore vs. mongodb.

hope that helps...

Community
  • 1
  • 1
lrivera
  • 514
  • 3
  • 8
  • Thanks for your reply. My code is written that way, I do have a service that extracts the image by UID and have a REST service to it, but a I commented above, I can't figure out a way to construct my own full url without hardcoding my own domain in the code (which I need in order to upload to facebook using that method of uploading via url) – Nadav Oct 02 '12 at 09:14
  • If you're talking about an HTTP request, you can find the request host in `request.headers.host`. But that relies on an incoming request. – lrivera Oct 02 '12 at 14:37
  • @Irivera - that works but feels like a really bad workaround to a rather straight-forward problem – Nadav Oct 05 '12 at 08:50