3

I am using Happstack, and I am trying to upload a photograph to Facebook using the Facebook Graph API.

I can successfully post a message to Facebook. I can use url, however I am trying to do this with the source parameter.

I have a ByteString of PNG data, but I can't seem to pass it along to Facebook.

I am using the fb Haskell library.

The functions that I have created to do this are:

performPost :: String -> IO Response
performPost code = do
    x <- BS.readFile "test.png"
    performFBAction $ do
        postToFB (BS.unpack x) code =<< getToken url2 code
        return $ toResponse postFB

postToFB :: (MonadResource m, MonadBaseControl IO m) => String -> String -> FB.UserAccessToken -> FB.FacebookT FB.Auth m FB.Id
postToFB dataString code token = FB.postObject "me/photos" [args "message" "Test Post Pls Ignore",
                                                            args "source" dataString] token

The error that I receive is:

The error was "StatusCodeException (Status {statusCode = 400, statusMessage = "Bad Request"}) [("Content-Type","text/html; charset=utf-8"),("Date","Thu, 29 Jan 2015 05:06:00 GMT"),("Connection","close"),("Content-Length","3121")] (CJ {expose = []})

What am I doing wrong? The Graph API states that the source parameter should be of type form data, but I have so far been unsuccessful in trying to convert it to such.

Thanks!

Moshe Katz
  • 15,992
  • 7
  • 69
  • 116
Citronen
  • 4,050
  • 4
  • 16
  • 20

2 Answers2

0

Please check whether the photo's content is encoded correctly. It need to be multipart/form-data as stated on

Tobi
  • 31,405
  • 8
  • 58
  • 90
  • Thank you for your answer, Tobi. I've tried to encode the data as `multipart/form` many different ways, but still receive the same error as above every time. Do you have any suggestions as to how to encode the PNG data? – Citronen Jan 29 '15 at 16:46
  • I'm not a Haskell expert, but did you have a look at https://hackage.haskell.org/package/happstack-server-7.3.9/docs/Happstack-Server-Internal-Multipart.html especially the multipartBody property? – Tobi Jan 29 '15 at 20:43
  • I've tried that, but I may be approaching the problem incorrectly. I've been trying to encode the data as `multipart/form-data` and send it along as a ByteString as a parameter. Should I somehow be trying to append the multipart to the request itself? – Citronen Jan 29 '15 at 23:35
  • As I said, I'm not a Haskell export. I'd try to append the multipart directly to the post request, I guess that is what it's for – Tobi Jan 30 '15 at 07:52
  • I have added the solution to my problem, but I have selected your answer as being correct. – Citronen Feb 01 '15 at 06:41
0

What Tobi said is correct. The code to correctly perform this operation is:

postPhoto :: FB.UserAccessToken -> IO Response
postPhoto (FB.UserAccessToken _ b _) = withSocketsDo $ withManager $ \m -> do
    fbpost <- parseUrl $ "https://graph.facebook.com/v2.2/me/photos?access_token=" ++ T.unpack b
    flip httpLbs m =<<
        (formDataBody [partBS "message" "Test Message",
                       partFileSource "graph" "graph.png"]
                      fbpost)
    return $ toResponse postFB

Enjoy!

Citronen
  • 4,050
  • 4
  • 16
  • 20