0

I'm having some trouble with a script that is attempting to upload a photo to a Facebook page. I had it working well when it was only strings being passed. A page post requires a source file (an image) and this is the part that I'm having trouble with. This returns a 400 Error.

I'm not totally sure how to handle the image (and the goal is doing this is bulk, so I'd ideally like a zip file of images.)

Here's the equivalent curl request that works correctly: curl -F 'message=Book p://bit.ly/alaska' -F 'source=@alaska.jpg' -F 'published=0' -F 'access_token=TEST' https://graph.facebook.com/act_id/photos

import os
import requests
import csv
import time
import thread
import zipfile
from datetime import datetime
from json import JSONEncoder
from flask import Flask, request, redirect, url_for, send_from_directory, \
                    render_template
from flask.ext.mail import Mail, Message
from werkzeug import secure_filename


email = ''
token=''
pageid = ''
filename = 'test.csv'
images = 'test.zip'
from flask import request

raw_input = open(filename, 'rb')
info = csv.DictReader(raw_input)
imagefile = zipfile.ZipFile(images, mode='r')        
creation_date = datetime.now().strftime('%m-%d-%Y')
output_csv_name = \
    "unpublished_posts_%s_%s.csv" % (pageid, creation_date)
output_csv = open(output_csv_name, 'wb')
writer = csv.writer(output_csv, quoting=csv.QUOTE_NONNUMERIC)
writer.writerow(('message',
    'source',
    'published',
    'scheduled_publish_time',
    'genders',
    'age_max',
    'age_min',
    'countries',
    'regions',
    'cities',
    'relationship_statuses',
    'interested_in',
    'locales',
    'education_statuses',
    'work_networks',
    'college_networks',
    'college_majors',
    'college_years',
    'post_id'
    ))

posts = []
targeting_params = ['genders',
    'age_max',
    'age_min',
    'countries',
    'regions',
    'cities',
    'relationship_statuses',
    'interested_in',
    'locales',
    'education_statuses',
    'work_networks',
    'college_networks',
    'college_majors',
    'college_years']

for idx, row in enumerate(list(info)):
    # convert date string to unix time-stamp
    if row['scheduled_publish_time'] <> '':
        s = row['scheduled_publish_time']
        timestamp = \
                    time.mktime(datetime.strptime(s, "%d/%m/%Y").timetuple())
                row['scheduled_publish_time'] = timestamp

    post_params = [s for s in row.keys() if s not in targeting_params]
    post_params.append('targeting')

    for param in targeting_params:
        if len(row[param]) > 0:
            row[param] = row[param].split(",")

    targeting_dict = {k: row[k] for k in targeting_params}
    targeting_dict = dict([(k, v) for k, v in targeting_dict.items() \
                                   if len(v) > 0])
    row['targeting'] = JSONEncoder().encode(targeting_dict)

    row = {k: row[k] for k in post_params}
    row = dict([(k, v) for k, v in row.items() if len(v) > 0])

    message = row['message']
    row[u'message'] = u''.join(unichr(ord(c)) for c in row['message'])  

    imagename = row[u'source']
    imagedata = imagefile.extract(imagename)
    files = {'source': open(imagedata, 'rb')}
    api_method = 'https://graph.facebook.com/%s/feed?access_token=%s'
    response = requests.post(api_method % (pageid, token),params=row,files=files)

Sorry if this isn't clear enough. Not sure what's pertinent and what's not. All I've changed from my previously working script is the addition of "files" in the request, so I'm pretty sure that's where I'm making a mistake.

Thanks!

1 Answers1

1

Try this :

files = { 'source': imagedata }

Basically you can't open() imagedata which is already a string (open() works only for files), so you just submit it as-is and Requests will take care of multipart-encoding it.

Also look at this question about file uploads using Requests.

Community
  • 1
  • 1