Reputation: 4351
I am writing a small app on Google App Engine to update the pictures in our users profiles. It takes there username and an image and does a put to there profile, uploading the image. Here is what i have:
import atom.data
import gdata.data
import gdata.contacts.client
import gdata.contacts.data
import cgi
import wsgiref.handlers
from google.appengine.api import users
from google.appengine.ext import webapp
email = '[email protected]'
password = 'password'
domain = 'domain.com'
gd_client = gdata.contacts.client.ContactsClient(domain=domain)
gd_client.ClientLogin(email, password, 'photoUpdate')
class PicPage(webapp.RequestHandler):
def get(self):
self.response.out.write("""<html><head><title>Sasaki Photo Uploader</title>
<link type="text/css" rel="stylesheet" href="/stylesheets/form.css"></head>
<body>
<form action="/" enctype="multipart/form-data" method="post">
<div><label>Person Name</label></div>
<div><textarea name="name" rows="2" columns "60"></textarea></div>
<div><label>Image</label></div>
<div><input type="file" name="img"/></div>
<div><input type="submit" value="Upload" /></div>
</form>
</body>
</html>""")
def post(self):
person_name = self.request.get('name')
img_img = self.request.get('img')
profile_url = 'https://www.google.com/m8/feeds/photos/profile/domain.com/%s' % person_name
media_object = img_img
print(profile_url)
profile = gd_client.GetProfile(profile_url)
print(profile)
gd_client.ChangePhoto(media_object, profile)
self.redirect('/')
def main():
application = webapp.WSGIApplication(
[('/', PicPage)
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__=="__main__":
main()
When I run this it returns the error:
Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\webapp\_webapp25.py", line 703, in __call__
handler.post(*groups)
File "C:\GAE_Local_Files\picupload\sasakipic.py", line 40, in post
profile = gd_client.GetProfile(profile_url)
File "C:\GAE_Local_Files\picupload\gdata\contacts\client.py", line 375, in get_profile
auth_token=auth_token, **kwargs)
File "C:\GAE_Local_Files\picupload\gdata\client.py", line 652, in get_entry
desired_class=desired_class, **kwargs)
File "C:\GAE_Local_Files\picupload\gdata\client.py", line 278, in request
version=get_xml_version(self.api_version))
File "C:\GAE_Local_Files\picupload\atom\core.py", line 520, in parse
tree = ElementTree.fromstring(xml_string)
File "<string>", line 106, in XML
ParseError: not well-formed (invalid token): line 1, column 0
i am not sure if this is because I am passing the profile url off as a string or uploading the pic wrong. Any advice, much appreciated.
EDIT Added full stack trace
Upvotes: 3
Views: 1224
Reputation: 4034
I have tried to use the script you posted above including the fix you've highlighted as a fix to the invalid token error, but for me that sprang a different error:
UnknownSize: Each part of the body must have a known size.
To rectify this I amended the line
media_object = img_img
to read:
media_object = gdata.data.MediaSource(img_img)
because the MediaSource object has implicit size and is one of accepted client.py parameters – except that a new error now springs up and i'm at a loss to know what to address.
RequestError: Server responded with: 400, Malformed Content-Type
i have tried adding a content-type='image/*' parameter to the ChangePhoto but it has no affect.
Any ideas?
error stream:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__
handler.post(*groups)
File " ...trim... /main.py", line 126, in post
gd_client.ChangePhoto(media_object, profile_url, content_type='image/*')
File " ...trim... /gdata/contacts/client.py", line 288, in change_photo
ifmatch_header=ifmatch_header, **kwargs)
File " ...trim... /atom/client.py", line 142, in put
http_request=http_request, data=data, **kwargs)
File " ...trim... /gdata/client.py", line 319, in request
RequestError)
RequestError: Server responded with: 400, Malformed Content-Type
Upvotes: 1
Reputation: 4351
Well, the answer lies in the issue that I pointed out in my edit. That line:
profile = gd_client.GetProfile(profile_url)
Is trying to query the picture located in the profile, but if it doesn't exist it breaks, so I edit the try statement to pass the profile url directly:
try:
gd_client.ChangePhoto(media_object, profile_url)
It worked great. This is a great little tool to update picture using App Engine, and you don't even have to upload it, just run it locally on a app engine test server. I want to try and add some functionality, like image cropping, or resizing before the upload, large images look fine on the contact profile page, but can get distorted in the chat image.
Upvotes: 1
Reputation: 8471
I believe the problem is you need to authenticate the request to the API. See here:
http://code.google.com/apis/contacts/docs/3.0/developers_guide.html#Auth
and look at this sample app for how the oauth flow works:
http://code.google.com/p/google-api-python-client/source/browse/samples/appengine/main.py
You might have a second problem that you need to specify the content-type of the file, but the first step is authenticating to get the profile.
Upvotes: 0