So, I’m writing Pictr.us in perl. And It is supposed to be able to upload images to flickr. After reading some sketchy documentation, I finally figured out how to accomplish this. It’s suprisingly easy.
I’m using the LWP::UserAgent module for all of my api requests to flickr, and it turns out that LWP will make the POST request with little hassle:
#####################
#
# function: flickr_upload
# parameters: filename, ... (array of filenames)
# returns: array of flickr photo_ids
#
# TODO: make error checking more robust
#
#####################
sub flickr_upload {
my @filenames = @_;
my @picids;
foreach my $filename (@filenames) {
my @filearray = ($filename, $filename);
my %vals;
$vals{'email'} = $flickr_email;
$vals{'password'} = $flickr_passwd;
$vals{'photo'} = \@filearray;
my $res = $ua->post(
'http://www.flickr.com/tools/uploader_go.gne',
\%vals, 'Content-type' => 'form-data');
my $doc = $parser->parse_string($res->content);
my @stati = $doc->getElementsByTagName('status');
if ($stati[0]->firstChild->data eq 'ok') {
my @idnodes=$doc->getElementsByTagName('photoid');
push @picids, $idnodes[0]->firstChild->data;
} else {
print "Something bad happened....";
}
}
return @picids;
# Now go to:
#'http://www.flickr.com/tools/uploader_edit.gne?ids='.
#join ',',@picids;
}
This is the key line:
my $res = $ua->post(
'http://www.flickr.com/tools/uploader_go.gne',
\%vals, 'Content-type' => 'form-data');
The first parameter is obviously the URL to post to. The second is a reference to a hash that contains the key=>value pairs (basically, the form fields). Notice that the value of ‘photo’ is an array reference. This tells LWP that this is a file upload. The first (0th) element in that array is the name of the file to upload, the second is the name to tell flickr for the file, I just used the same name. This array can also contain additional values that I didn’t used, info here. The third parameter is the Content type header. This is very important. If you leave it off LWP will try to use the “key=value&key=value&….” syntax, and it really has to be multipart form data.
The rest is pretty simple. I’m using XML::LibXML to parse the responses from flickr.