Importing data from WebDAV
For this howto, we will use the ATBookmark product as an example. This product already has the capability of importing XBEL files, and transforming the file into a collection of Link objects.
Now we would like to learn from Sidnei da Silva's Calendaring product on how to enhance ATBookmark to do this transformation when an XBEL file is uploaded via WebDAV.
We need to modify the BookmarkFolder class in ATBookmarks/BookmarkFolder.py:
NOTE: the following code has not been fully tested nor is it known to work in ATBookmarks. This howto is still a work-in-progress.
Override the PUT method
Since we want to do something special with the file after it's uploaded when need to override Zope's default built-in PUT method.
security.declareProtected(CMFCorePermissions.ModifyPortalContent, 'PUT')
def PUT(self, REQUEST=None, RESPONSE=None):
""" HTTP PUT handler """
if not REQUEST:
REQUEST = self.REQUEST
if not RESPONSE:
RESPONSE = REQUEST.RESPONSE
self.dav__init(REQUEST, RESPONSE)
self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
file = REQUEST['BODYFILE']
data = file.read()
file.seek(0)
if not hasattr(self, 'aq_parent'):
# XXX We don't have access to portal_calendar
# yet at this time, so we create a volatile
# attribute and check it on afterAdd.
self._v_upload = file
else:
self.fromFile(file)
self.reindexObject()
RESPONSE.setStatus(204)
return RESPONSE
Override the manage_afterAdd method
If we weren't able to process the file in the PUT, then we do it here. Sidnei - can you provide a better explanation for this?
def manage_afterAdd(self, item, container):
BaseFolder.manage_afterAdd(self, item, container)
# If the volatile attribute was set
# in PUT, then we get the file and
# import it.
file = getattr(self, '_v_upload', None)
if file is not None:
self.fromFile(file)
self.reindexObject()
Create a fromFile method:
Next you need to write code for how to handle the file once it's uploaded. In the case of a XBEL file, we want to use an XML parser to extract each link's title, description and URL.
def fromFile(self, stream):
""" Import bookmarks from a file into this folder """
m = MyHandler()
parser = make_parser()
parser.setContentHandler(m)
parser.parse(stream)
f = m.currentFolder
self.convertFolder(self, f)
Add an extension predicate in the content_type_registry
In order for Zope to know what to do with files with the extension of .xbel, we need to create a mapping in the content_type_registry. Add a new predicate like the following:
xbel_ext: xbel -> BookmarkFolder
FTP Handling
XXX Need to write method for manage_FTPget
Deleting the object
XXX Need to write method for manage_beforeDelete
Other examples
Just as we have done with XBEL files, the following file formats could be uploaded via WebDAV into a Plone site using a similar method to the one described above:
- vCard contact files (.vcf) starting with Stephen Corey's PloneContacts
- JPG photos from iPhoto starting with Frasier Speir's iPhoto Plugin for Flickr (open source BSD license)
- other ideas?
