Ticket #6390: S3_6390.20080321.py

File S3_6390.20080321.py, 3.2 KB (added by David Larlet, 16 years ago)

New S3 storage which works with the latest storage patch (14) with new functions' names, I'm not totally satisfied with the way arguments are passed, I'll try to do it better

Line 
1from mimetypes import guess_type
2from StringIO import StringIO
3import urlparse
4import os
5
6from django.core.exceptions import ImproperlyConfigured
7from django.core.filestorage.base import Storage, RemoteFile
8from django.core.filestorage.filesystem import FileSystemStorage
9from django.utils.functional import curry
10from django.conf import settings
11
12ACCESS_KEY_NAME = 'AWS_ACCESS_KEY_ID'
13SECRET_KEY_NAME = 'AWS_SECRET_ACCESS_KEY'
14
15try:
16 from _lib.amazon.S3 import AWSAuthConnection, QueryStringAuthGenerator
17except ImportError:
18 raise ImproperlyConfigured, "Could not load amazon's S3 bindings.\
19 \nSee http://developer.amazonwebservices.com/connect/entry.jspa?externalID=134"
20
21class S3Storage(Storage):
22 """Amazon Simple Storage Service"""
23
24 def __init__(self, bucket=settings.AWS_STORAGE_BUCKET_NAME,
25 access_key=None, secret_key=None, acl='public-read',
26 calling_format=settings.AWS_CALLING_FORMAT):
27 self.bucket = bucket
28 self.acl = acl
29
30 if not access_key and not secret_key:
31 access_key, secret_key = self._get_access_keys()
32
33 self.connection = AWSAuthConnection(access_key, secret_key,
34 calling_format=calling_format)
35 self.generator = QueryStringAuthGenerator(access_key, secret_key,
36 calling_format=calling_format, is_secure=False)
37
38 def _get_access_keys(self):
39 access_key = getattr(settings, ACCESS_KEY_NAME, None)
40 secret_key = getattr(settings, SECRET_KEY_NAME, None)
41 if (access_key or secret_key) and (not access_key or not secret_key):
42 access_key = os.environ.get(ACCESS_KEY_NAME)
43 secret_key = os.environ.get(SECRET_KEY_NAME)
44
45 if access_key and secret_key:
46 # Both were provided, so use them
47 return access_key, secret_key
48
49 return None, None
50
51 def _get_connection(self):
52 return AWSAuthConnection(*self._get_access_keys())
53
54 def _put_file(self, filename, raw_contents):
55 content_type = guess_type(filename)[0] or "application/x-octet-stream"
56 headers = {'x-amz-acl': self.acl, 'Content-Type': content_type}
57 response = self.connection.put(self.bucket, filename, raw_contents, headers)
58
59 def url(self, filename):
60 return self.generator.make_bare_url(self.bucket, filename)
61
62 def filesize(self, filename):
63 response = self.connection.make_request('HEAD', self.bucket, filename)
64 return int(response.getheader('Content-Length'))
65
66 def open(self, filename, mode='rb'):
67 response = self.connection.get(self.bucket, filename)
68 writer = curry(self._put_file, filename)
69 return RemoteFile(self, response.object.data, mode, writer)
70
71 def exists(self, filename):
72 response = self.connection.make_request('HEAD', self.bucket, filename)
73 return response.status == 200
74
75 def save(self, filename, raw_contents):
76 filename = self.get_available_filename(filename)
77 self._put_file(filename, raw_contents)
78 return filename
79
80 def delete(self, filename):
81 self.connection.delete(self.bucket, filename)
82
83 def get_available_filename(self, filename):
84 """ Overwrite existing file with the same name. """
85 return filename
Back to Top