Warning

This document hasn't been checked for compatibility with current versions of Plone. Use at your own risk.

Importing data from WebDAV

by Nate Aune last modified Dec 06, 2009 09:27 PM
Many times we would like to upload some content via WebDAV, and have it automatically transformed into Plone content objects. This howto uses the example of uploading an XBEL file and transforming it into a folder of Link objects.

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?

Contribute

Something wrong or out of date? Anybody can edit or create a new article in the knowledge base. Simply create an account on this site, log in, and click the Edit button to contribute.