Created
April 28, 2014 09:04
-
-
Save FZambia/11366204 to your computer and use it in GitHub Desktop.
webdav storage backend for django
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
from urlparse import urljoin | |
from django.conf import settings | |
from django.core.files.storage import Storage | |
import logging | |
from urlparse import urlparse | |
import requests | |
logger = logging.getLogger('webdav') | |
class WebDAVException(Exception): | |
pass | |
class WebDAVStorage(Storage): | |
""" | |
WebDAV Storage class for Django | |
""" | |
def __init__(self, locations=settings.WEBDAV_LOCATIONS): | |
self._locations = locations | |
self._base_path = urlparse(settings.MEDIA_URL).path | |
def _get_full_path(self, location, name): | |
return urljoin(urljoin(location, self._base_path), name) | |
def exists(self, name): | |
logger.debug(u'checking existing of {0}'.format(name)) | |
file_found = False | |
# check all dav instances for file existence, | |
# if file exist in one of them then we think that file exists | |
for location in self._locations: | |
logger.debug(u'checking via location {0}'.format(location)) | |
response = requests.head(self._get_full_path(location, name)) | |
if response.status_code == 200: | |
file_found = True | |
logger.debug(u'file found') | |
break | |
if not file_found: | |
logger.debug(u'file does not exist') | |
return file_found | |
def _save(self, name, content): | |
logger.debug(u'saving {0}'.format(name)) | |
is_tmp_file = hasattr(content.file, 'temporary_file_path') | |
if is_tmp_file: | |
data = None | |
logger.debug(u"uploading from temporary file") | |
else: | |
# read content into memory | |
logger.debug(u"uploading from memory") | |
data = content.read() | |
for location in self._locations: | |
logger.debug(u'saving in {0}'.format(location)) | |
if is_tmp_file: | |
# send file without loading it in memory | |
with open(content.file.temporary_file_path()) as f: | |
response = requests.put(self._get_full_path(location, name), data=f) | |
else: | |
response = requests.put( | |
self._get_full_path(location, name), data=data | |
) | |
if response.status_code not in (201, 204): | |
msg = u"uploading {0}: status code {1}".format( | |
self._get_full_path(location, name), response.status_code | |
) | |
logger.error(msg) | |
raise WebDAVException(msg) | |
logger.debug(u'{0} successfully saved'.format(name)) | |
return name | |
def _open(self, name, mode): | |
raise NotImplementedError | |
def _read(self, name): | |
raise NotImplementedError() | |
def delete(self, name): | |
logger.debug(u'deleting {0}'.format(name)) | |
for location in self._locations: | |
logger.debug(u'deleting in {0}'.format(location)) | |
response = requests.delete(self._get_full_path(location, name)) | |
if response.status_code not in (204,): | |
msg = u"deleting {0}: status code {1}".format(self._get_full_path(location, name), response.status_code) | |
logger.error(msg) | |
raise WebDAVException(msg) | |
logger.debug(u'{0} deleted'.format(name)) | |
def url(self, name): | |
return urljoin(settings.MEDIA_URL, name) | |
def size(self, name): | |
logger.debug(u'getting {0} size'.format(name)) | |
for location in self._locations: | |
logger.debug(u'getting via {0}'.format(location)) | |
try: | |
response = requests.head(self._get_full_path(location, name), timeout=1) | |
except Exception as err: | |
logger.exception(err) | |
else: | |
return response.headers.get('Content-Length') | |
logger.error(u'file size not found') | |
return None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment