Previously described bash script allows for uploading a file to PicasaWeb only. With the following (simplified) Perl script one can upload pictures as well as upload with metadata (title description and tags) or create/list albums:
#!/usr/bin/perl use strict; use LWP::UserAgent; use Getopt::Long; use File::MimeInfo; use XML::LibXML; my $AlbumId ="6170354040646469009"; my $profileID="default"; my $Action = 'u'; ## x| u | c | l (default action is Upload) my $entryTitle = ''; my $entryDescription = ''; my $entryKeywords = ''; my $ActionUpload =''; my $ActionList = ''; my $ActionCreate = ''; my $ActionXload = ''; my $ImageFile = ''; my $dummyReq=''; GetOptions("xload" => \$ActionXload, "upload" => \$ActionUpload, "list" => \$ActionList, "create" => \$ActionCreate, "title=s" => \$entryTitle, "description=s" => \$entryDescription, "keywords=s" => \$entryKeywords, "file=s" => \$ImageFile, "album=s" => \$AlbumId, ## UploadFile to Album ) ; ## Determine action: if ( $ActionUpload ) {$Action = 'u'} elsif ( $ActionList ) { $Action = 'l'} elsif ( $ActionCreate ) { $Action = 'c'} elsif ( $ActionXload ) { $Action = 'x'}
OAuth 2.0 authorization is handled with Python script
oauth2picasa.py
. The script is an adapted/copy-pasted fragment
of code borrowd from
picasawebsync
:
### Authenticate with external script (oauth2picasa.py): my $ACCESS_TOKEN=`oauth2picasa.py`; chomp($ACCESS_TOKEN); print STDERR "*** AccessToken: $ACCESS_TOKEN [AlbumId: $AlbumId]\n"; my $req ; my $blog_entry ; my $picasawebURL = "https://picasaweb.google.com/data/feed/api/user/$profileID"; if ( $Action eq 'c' ) {## Action: create album $req = HTTP::Request->new(POST => $picasawebURL ); $req->header( 'Content-Type' => 'application/atom+xml' ); $blog_entry = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gphoto='http://schemas.google.com/photos/2007'>" . "<title type='text'>$entryTitle</title>" . "<summary type='text'>$entryDescription</summary>" . "<media:group><media:keywords>$entryKeywords</media:keywords></media:group>" . "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'></category></entry>"; $req->content($blog_entry); } elsif ( $Action eq 'l' ) {## Action: list albums $req = HTTP::Request->new(GET => $picasawebURL ); } elsif ( $Action eq 'u' ) {## Action: Upload 1 photo w/o metadata my $mimeType = mimetype($ImageFile); ## https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol $req = HTTP::Request->new(POST => "$picasawebURL/albumid/$AlbumId" ); $req->header( 'Content-Type' => "$mimeType" ); $req->header( 'Slug' => "$ImageFile" ); ## http://www.perlmonks.org/?node_id=131584 open(FILE, $ImageFile); $req->content(join('',<FILE>)); close(FILE); }
To upload the binary image data along with its metadata, use MIME content
type "multipart/related"; send photo metadata in one part of the POST
body (Content-Type: application/atom+xml
),
and binary-encoded image data in another part.
This is the preferred approach according to
Picasa Web Albums Data API
Picasa Web Albums Data API
elsif ( $Action eq 'x' ) {## Action: Upload 1 photo with metadata # https://groups.google.com/forum/#!topic/google-picasa-data-api/2qRfP0EIFhk my $mimeType = mimetype($ImageFile); $req = HTTP::Request->new(POST => "$picasawebURL/albumid/$AlbumId" ); $req->header( 'Content-Type' => "multipart/related" ); open(FILE, $ImageFile); my $add_photo_metadata = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'>" . "<title type='text'>$entryTitle</title>" . "<summary type='text'>$entryDescription</summary>" . "<media:group><media:keywords>$entryKeywords</media:keywords></media:group>" . "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#photo'></category></entry>"; my $add_photo_data = join('',<FILE>); close(FILE); ## http://www.perlmonks.org/?node_id=131584 $req->add_part(HTTP::Message->new(['Content-Type' => 'application/atom+xml'], $add_photo_metadata)); $req->add_part(HTTP::Message->new(['Content-Type' => "$mimeType"], $add_photo_data)); } $req->header( 'Authorization' => "Bearer $ACCESS_TOKEN" ); $req->header( 'GData-Version' => '2' ); ## ### ### my $res ; my $ua = LWP::UserAgent->new; $res = $ua->request($req); if ($res->is_success) { my $decoded_response = $res->decoded_content; print "*** OK *** $decoded_response\n"; }
Usage:
Upload with metadata
picasaweb.pl -xload -title PICTURE-TITLE -descr DESCRIPTION \ -keywords 'TAG1,TAG2' -file FILE.jpg -album ALBUMID
Upload w/o metadata:
picasaweb.pl -upload -file FILE.jpg -album 12345
Create album:
picasaweb.pl -create -title ALBUM-TITLE -descr DESCRIPTION \ -keywords 'TAG1,TAG2'
List album:
picasaweb.pl -list
Source code:
picasaweb.pl
Taki oto (uproszczony) skrypt basha używałem do niedawna do wysyłania plików na konto Picasaweb (por. Using cURL to interact with Google Data services oraz PicasaUploader):
USERNAME=SomeUsername # GoogleAccountUsername PASSWORD=SomePasswd # GoogleAccountPasswd ALBUM_ID=6008849823888405298 # ID of picasaweb album MY_PIC="$1" ## filename of the picture to upload ## PIC_TITLE=`basename $MY_PIC` # filename w/o extension PIC_TYPE=`file -b --mime-type "$MY_PIC"` AUTH_KEY=$( curl -s https://www.google.com/accounts/ClientLogin -d Email="$USERNAME"@gmail.com \ -d Passwd="$PASSWORD" -d accountType=GOOGLE \ -d source=Google-cURL-Example -d service=lh2 | awk -F\= '/^Auth=/{print $2}' ) ALBUM_XML="http://picasaweb.google.com/data/feed/api/user/$USER_ID/albumid/$ALBUM_ID?authkey=$AUTH_KEY" URL=`curl -s --request POST --data-binary "@$MY_PIC" --header "Slug: $PIC_TITLE" \ --header "Content-Type: $PIC_TYPE" \ --header "Authorization: GoogleLogin auth=$AUTH_KEY" "$ALBUM_XML" | \ sed 's/.*media:content url='"'"'\([^'"'"']*\).*media:thumbnail url='"'"'\([^'"'"']*\).*/\1/'`
Zmienna URL
zawiera url wysłanego na Picasaweb obrazka (otrzymany
przez zaaplikowanie w potoku odpowiedniego skryptu seda).
Skrypt przestał działać ostatnio, ponieważ Google nie obsługuje już protokołu OAuth 1.0 (por. Google Identity Platform). Na szczęście w łatwy sposób możliwe było dopasowanie skryptu nowszego protokołu OAuth 2.0:
ACCESS_TOKEN=$(oauth2picasa.py) ## Acces token is managed with Python's script now ## Note that ALBUM_XML URL starts now from https:// now ALBUM_XML="https://picasaweb.google.com/data/feed/api/user/$USER_ID/albumid/$ALBUM_ID" URL=`curl -s --request POST --data-binary "@$MY_PIC" \ --header "GData-Version: 2" --header "Slug: $PIC_TITLE" \ --header "Content-Type: $PIC_TYPE" -H "Authorization: Bearer $ACCESS_TOKEN" $ALBUM_XML | \ sed 's/.*media:content url='"'"'\([^'"'"']*\).*media:thumbnail url='"'"'\([^'"'"']*\).*/\1/'`
Uwaga: Autoryzację OAuth 2.0 obsługuje Pythonowy skrypt oauth2picasa.py
.
Skrypt jest (zapożyczonym) fragmentem z projektu
picasawebsync
:
#!/usr/bin/python import os import time import httplib2 ## https://github.com/google/oauth2client ## installed with pip install --upgrade oauth2client (or some other way) from oauth2client import client def oauthLogin(): # using http://stackoverflow.com/questions/20248555/list-of-spreadsheets-gdata-oauth2/29157967#29157967 from oauth2client.file import Storage filename = os.path.join(os.path.expanduser('~'), ".picasawebsync") client_secrets = os.path.join(os.path.expanduser('~'), ".config", "picasawebsync.json") storage = Storage(filename) credentials = storage.get() if credentials is None or credentials.invalid: flow = client.flow_from_clientsecrets(client_secrets, scope='https://picasaweb.google.com/data/', redirect_uri='urn:ietf:wg:oauth:2.0:oob') auth_uri = flow.step1_get_authorize_url() print 'Authorization URL: %s' % auth_uri auth_code = raw_input('Enter the auth code: ') credentials = flow.step2_exchange(auth_code) storage.put(credentials) if credentials.access_token_expired: credentials.refresh(httplib2.Http()) return credentials.access_token # start of the program gd_client = oauthLogin() print '%s' % gd_client
Jak stworzyć OAuth 2.0 client ID opisano
tutaj.
Należy wybrać Client ID for native application. Następnie należy pobrać plik JSON
,
zmienić nazwę tego pliku na
picasawebsync.json
umieszczając go w katalogu .config
swojego katalogu domowego (albo zmodyfikować skrypt, jeżeli plik ma być w innym miejscu).
Uruchomiony po raz pierwszy skrypt oauth2picasa.py
wypisuje URL, który należy
skopiować/wkleić do przeglądarki, celem uzyskania authcode.
Pobrany authcode
wklejamy w odpowiedzi na prompt Enter the auth code:.
Opisane skrypty są tutaj: picasa_upld.sh
oraz oauth2picasa.py
.
My (simplified) old bash script for uploading images to Picasaweb (cf. Using cURL to interact with Google Data services and PicasaUploader):
USERNAME=SomeUsername # GoogleAccountUsername PASSWORD=SomePasswd # GoogleAccountPasswd ALBUM_ID=6008849823888405298 # ID of picasaweb album MY_PIC="$1" ## filename of the picture to upload ## PIC_TITLE=`basename $MY_PIC` # filename w/o extension PIC_TYPE=`file -b --mime-type "$MY_PIC"` AUTH_KEY=$( curl -s https://www.google.com/accounts/ClientLogin -d Email="$USERNAME"@gmail.com \ -d Passwd="$PASSWORD" -d accountType=GOOGLE \ -d source=Google-cURL-Example -d service=lh2 | awk -F\= '/^Auth=/{print $2}' ) ALBUM_XML="http://picasaweb.google.com/data/feed/api/user/$USER_ID/albumid/$ALBUM_ID?authkey=$AUTH_KEY" URL=`curl -s --request POST --data-binary "@$MY_PIC" --header "Slug: $PIC_TITLE" \ --header "Content-Type: $PIC_TYPE" \ --header "Authorization: GoogleLogin auth=$AUTH_KEY" "$ALBUM_XML" | \ sed 's/.*media:content url='"'"'\([^'"'"']*\).*media:thumbnail url='"'"'\([^'"'"']*\).*/\1/'`
URL
contains url of uploaded picture (obtained with piping curl's output via sed).
This script stoped working recently as Google no longer supports OAuth 1.0 (cf. Google Identity Platform). Fortunately it was pretty easy to modify it to support OAuth 2.0:
ACCESS_TOKEN=$(oauth2picasa.py) ## Acces token is managed with Python's script now ## Note that ALBUM_XML URL starts now from https:// now ALBUM_XML="https://picasaweb.google.com/data/feed/api/user/$USER_ID/albumid/$ALBUM_ID" URL=`curl -s --request POST --data-binary "@$MY_PIC" \ --header "GData-Version: 2" --header "Slug: $PIC_TITLE" \ --header "Content-Type: $PIC_TYPE" -H "Authorization: Bearer $ACCESS_TOKEN" $ALBUM_XML | \ sed 's/.*media:content url='"'"'\([^'"'"']*\).*media:thumbnail url='"'"'\([^'"'"']*\).*/\1/'`
NOTE: OAuth 2.0 authorization is handled with tiny Python script
oauth2picasa.py
. The script is an adapted/copy-pasted fragment
of code borrowd from
picasawebsync
:
#!/usr/bin/python import os import time import httplib2 ## https://github.com/google/oauth2client ## installed with pip install --upgrade oauth2client (or some other way) from oauth2client import client def oauthLogin(): # using http://stackoverflow.com/questions/20248555/list-of-spreadsheets-gdata-oauth2/29157967#29157967 from oauth2client.file import Storage filename = os.path.join(os.path.expanduser('~'), ".picasawebsync") client_secrets = os.path.join(os.path.expanduser('~'), ".config", "picasawebsync.json") storage = Storage(filename) credentials = storage.get() if credentials is None or credentials.invalid: flow = client.flow_from_clientsecrets(client_secrets, scope='https://picasaweb.google.com/data/', redirect_uri='urn:ietf:wg:oauth:2.0:oob') auth_uri = flow.step1_get_authorize_url() print 'Authorization URL: %s' % auth_uri auth_code = raw_input('Enter the auth code: ') credentials = flow.step2_exchange(auth_code) storage.put(credentials) if credentials.access_token_expired: credentials.refresh(httplib2.Http()) return credentials.access_token # start of the program gd_client = oauthLogin() print '%s' % gd_client
How to create an OAuth 2.0 client ID in the Google Developers Console is described
here.
Choose Client ID for native application. Next download JSON
file, rename it to
picasawebsync.json
and move it to .config
directory in your HOME
directory (or modify the script).
First time used oauth2picasa.py
prompts to sign on to google
and paste the link back to authenticate.
Source code: picasa_upld.sh
and oauth2picasa.py
.
Nie mogę się zalogować w programie picasa (wersja dla linuksa, 3.0 beta). Wpisując Picasa Linux signup problem do Google znalazłem podpowiedź:
cp /usr/lib/wine/wininet.dll.so /opt/google/picasa/3.0/wine/lib/wine/
U mnie przynajmniej powyższe działa.
Się przy okazji okazało, że zdjęcia zawierające współrzędne geograficzne przesłane via formularz nie są traktowane jako geotagowane . Picasaweb rozpoznaje zdjęcia jako geotagowane jeżeli są ładowane programem picasa. Na flickr.com jest pod tym względem prościej, bo współrzędne geograficzne są pobierane ze zdjęcia po stronie serwera--wystarczy przesłać plik i nie jest istotne w jaki sposób...