initial commit
[namibia] / public / scripts / blueimp-jQuery-File-Upload / server / gae-python / main.py
1 # -*- coding: utf-8 -*-
2 #
3 # jQuery File Upload Plugin GAE Python Example 1.1.4
4 # https://github.com/blueimp/jQuery-File-Upload
5 #
6 # Copyright 2011, Sebastian Tschan
7 # https://blueimp.net
8 #
9 # Licensed under the MIT license:
10 # http://www.opensource.org/licenses/MIT
11 #
12
13 from __future__ import with_statement
14 from google.appengine.api import files, images
15 from google.appengine.ext import blobstore, deferred
16 from google.appengine.ext.webapp import blobstore_handlers
17 import json, re, urllib, webapp2
18
19 WEBSITE = 'http://blueimp.github.com/jQuery-File-Upload/'
20 MIN_FILE_SIZE = 1 # bytes
21 MAX_FILE_SIZE = 5000000 # bytes
22 IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)')
23 ACCEPT_FILE_TYPES = IMAGE_TYPES
24 THUMBNAIL_MODIFICATOR = '=s80' # max width / height
25 EXPIRATION_TIME = 300 # seconds
26
27 def cleanup(blob_keys):
28     blobstore.delete(blob_keys)
29
30 class UploadHandler(webapp2.RequestHandler):
31
32     def initialize(self, request, response):
33         super(UploadHandler, self).initialize(request, response)
34         self.response.headers['Access-Control-Allow-Origin'] = '*'
35         self.response.headers[
36             'Access-Control-Allow-Methods'
37         ] = 'OPTIONS, HEAD, GET, POST, PUT, DELETE'
38     
39     def validate(self, file):
40         if file['size'] < MIN_FILE_SIZE:
41             file['error'] = 'minFileSize'
42         elif file['size'] > MAX_FILE_SIZE:
43             file['error'] = 'maxFileSize'
44         elif not ACCEPT_FILE_TYPES.match(file['type']):
45             file['error'] = 'acceptFileTypes'
46         else:
47             return True
48         return False
49     
50     def get_file_size(self, file):
51         file.seek(0, 2) # Seek to the end of the file
52         size = file.tell() # Get the position of EOF
53         file.seek(0) # Reset the file position to the beginning
54         return size
55     
56     def write_blob(self, data, info):
57         blob = files.blobstore.create(
58             mime_type=info['type'],
59             _blobinfo_uploaded_filename=info['name']
60         )
61         with files.open(blob, 'a') as f:
62             f.write(data)
63         files.finalize(blob)
64         return files.blobstore.get_blob_key(blob)
65     
66     def handle_upload(self):
67         results = []
68         blob_keys = []
69         for name, fieldStorage in self.request.POST.items():
70             if type(fieldStorage) is unicode:
71                 continue
72             result = {}
73             result['name'] = re.sub(r'^.*\\', '',
74                 fieldStorage.filename)
75             result['type'] = fieldStorage.type
76             result['size'] = self.get_file_size(fieldStorage.file)
77             if self.validate(result):
78                 blob_key = str(
79                     self.write_blob(fieldStorage.value, result)
80                 )
81                 blob_keys.append(blob_key)
82                 result['delete_type'] = 'DELETE'
83                 result['delete_url'] = self.request.host_url +\
84                     '/?key=' + urllib.quote(blob_key, '')
85                 if (IMAGE_TYPES.match(result['type'])):
86                     try:
87                         result['url'] = images.get_serving_url(
88                             blob_key,
89                             secure_url=self.request.host_url\
90                                 .startswith('https')
91                         )
92                         result['thumbnail_url'] = result['url'] +\
93                             THUMBNAIL_MODIFICATOR
94                     except: # Could not get an image serving url
95                         pass
96                 if not 'url' in result:
97                     result['url'] = self.request.host_url +\
98                         '/' + blob_key + '/' + urllib.quote(
99                             result['name'].encode('utf-8'), '')
100             results.append(result)
101         deferred.defer(
102             cleanup,
103             blob_keys,
104             _countdown=EXPIRATION_TIME
105         )
106         return results
107     
108     def options(self):
109         pass
110         
111     def head(self):
112         pass
113     
114     def get(self):
115         self.redirect(WEBSITE)
116     
117     def post(self):
118         if (self.request.get('_method') == 'DELETE'):
119             return self.delete()
120         s = json.dumps(self.handle_upload(), separators=(',',':'))
121         redirect = self.request.get('redirect')
122         if redirect:
123             return self.redirect(str(
124                 redirect.replace('%s', urllib.quote(s, ''), 1)
125             ))
126         if 'application/json' in self.request.headers.get('Accept'):
127             self.response.headers['Content-Type'] = 'application/json'
128         self.response.write(s)
129
130     def delete(self):
131         blobstore.delete(self.request.get('key') or '')
132
133 class DownloadHandler(blobstore_handlers.BlobstoreDownloadHandler):
134     def get(self, key, filename):
135         if not blobstore.get(key):
136             self.error(404)
137         else:
138             # Cache for the expiration time:
139             self.response.headers['Cache-Control'] =\
140                 'public,max-age=%d' % EXPIRATION_TIME
141             self.send_blob(key, save_as=filename)
142
143 app = webapp2.WSGIApplication(
144     [
145         ('/', UploadHandler),
146         ('/([^/]+)/([^/]+)', DownloadHandler)
147     ],
148     debug=True
149 )