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!