Merge branch 'master' of github.com:FinalsClub/karmaworld
[oweals/karmaworld.git] / karmaworld / apps / ajaxuploader / README.md
1 `django-ajax-uploader` provides a useful class you can use to easily implement ajax uploads.
2
3 It uses valum's great uploader: https://github.com/valums/file-uploader, and draws heavy inspiration and some code from 
4 https://github.com/alexkuhl/file-uploader
5
6 In short, it implements a callable class, `AjaxFileUploader` that you can use to handle uploads. By default, `AjaxFileUploader` assumes you want to upload to local storage, but you can select any other backend if desired or write your own (see backends section below). Pull requests welcome!
7
8 Updates
9 =======
10
11 Version 0.2.1 is released, and contains:
12
13 * JSON parsing of `extra_context` now properly handles datetimes. (Thanks to onyxfish)
14
15
16 Version 0.2 is released, and contains:
17         
18 * Optional `fileLimit` param for the uploader, to limit the number of allowed files. (Thanks to qnub)
19 * fhahn's `default_storage` backend.
20  
21
22 Version 0.1.1 is released, and contains:
23
24 * Support for a CouchDB backend
25 * A backwards-incompatible change to the location of the ajaxuploader static files. I try to avoid backwards incompatibilities, but since /js and /css are the proper conventions and the lib is relatively young, it seemed better to get things right now, instead of waiting. The static files are now at:
26   * `{{STATIC_URL}}ajaxuploader/js/fileuploader.js`
27   * `{{STATIC_URL}}ajaxuploader/css/fileuploader.css`
28  
29
30 Usage
31 =====
32 Step 1. Install django-ajax-uploader. 
33 -------------------------------------
34 It's in pypi now, so simply:
35
36 - `pip install ajaxuploader`
37
38 You may also need to install backend-specific dependences. 
39
40  - For the S3 backend, you will need [boto](https://github.com/boto/boto).  ( `pip install boto` )
41  - For the MongoDB GridFS backend, you will need [pymongo](https://github.com/AloneRoad/pymongo) ( `pip install pymongo` )
42
43 Step 2. (Django 1.3 only)
44 -------------------------
45 For Django 1.3 you will need to have the app in your installed apps tuple for collect static to pick up the files.
46
47 First Add 'ajaxuploader' to you installed apps in settings.py
48
49 ```
50 INSTALLED_APPS = (
51     ...
52     "ajaxuploader",
53 )
54 ```
55
56 Then:
57
58 ```
59 $ python manage.py collectstatic
60 ```
61
62 Step 3. Include it in your app's views and urls.
63 ------------------------------------------------
64 You'll need to make sure to meet the csrf requirements to still make valum's uploader work.  Code similar to the following should work:
65
66 views.py
67
68 ```python
69 from django.middleware.csrf import get_token
70 from django.shortcuts import render_to_response
71 from django.template import RequestContext
72
73 from ajaxuploader.views import AjaxFileUploader
74
75
76 def start(request):
77     csrf_token = get_token(request)
78     return render_to_response('import.html',
79         {'csrf_token': csrf_token}, context_instance = RequestContext(request))
80
81 import_uploader = AjaxFileUploader()
82 ```     
83
84 urls.py 
85
86 ```
87 url(r'start$', views.start, name="start"),
88 url(r'ajax-upload$', views.import_uploader, name="my_ajax_upload"),
89 ```
90
91 Step 4. Set up your template.
92 -----------------------------
93 This sample is included in the templates directory, but at the minimum, you need:
94
95 ```html
96 <!doctype html>
97     <head>
98                 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" ></script>
99         <script src="{{ STATIC_URL }}ajaxuploader/js/fileuploader.js" ></script>
100         <link href="{{ STATIC_URL }}ajaxuploader/css/fileuploader.css" media="screen" rel="stylesheet" type="text/css" />
101         <script>
102                 $(function(){
103             var uploader = new qq.FileUploader({
104                 action: "{% url my_ajax_upload %}",
105                 element: $('#file-uploader')[0],
106                 multiple: true,
107                 onComplete: function(id, fileName, responseJSON) {
108                     if(responseJSON.success) {
109                         alert("success!");
110                     } else {
111                         alert("upload failed!");
112                     }
113                 },
114                 onAllComplete: function(uploads) {
115                     // uploads is an array of maps
116                     // the maps look like this: {file: FileObject, response: JSONServerResponse}
117                     alert("All complete!");
118                 },
119                 params: {
120                     'csrf_token': '{{ csrf_token }}',
121                     'csrf_name': 'csrfmiddlewaretoken',
122                     'csrf_xname': 'X-CSRFToken',
123                 },
124             });
125                 });
126         </script>
127     </head>
128 <body>
129     <div id="file-uploader">       
130         <noscript>          
131             <p>Please enable JavaScript to use file uploader.</p>
132         </noscript>         
133     </div>
134 </body>
135 </html>
136 ```
137
138 Backends
139 ========
140
141 `django-ajax-uploader` can put the uploaded files into a number of places, and perform actions on the files uploaded. Currently, 
142 there are backends available for local storage (default), Amazon S3, MongoDB (GridFS), CouchDB, and a locally stored image 
143 thumbnail backend. Creating a custom backend is fairly straightforward, and pull requests are welcome.
144
145 Built-in Backends
146 ------------------
147
148 `django-ajax-uploader` has the following backends:
149
150 ### local.LocalUploadBackend ###
151
152 Stores the file locally, by default to `{MEDIA_ROOT}/uploads`.
153
154 Requirements:
155
156 * None
157
158 Settings:
159
160 * `UPLOAD_DIR` : The directory to store the uploaded file in, within `MEDIA_ROOT`. Defaults to "uploads".
161 * `BUFFER_SIZE`: The size of each chunk to write. Defaults to 10 MB.  See the caveat at the bottom before changing it.
162
163 Context returned:
164
165 * `path`: The full media path to the uploaded file.
166
167
168 ### mongodb.MongoDBUploadBackend ###
169
170 Stores the file in MongoDB via GridFS
171
172 Requirements
173
174 * [pymongo](https://github.com/AloneRoad/pymongo)
175
176 Settings:
177
178 * `AJAXUPLOAD_MONGODB_HOST`: Specify the host of your MongoDB server. Defaults to localhost if not specified.
179 * `AJAXUPLOAD_MONGODB_PORT`: Specify the port of your MongoDB server. Defaults to 27017 if not specified.
180
181 Arguments
182
183 * db (required): Specify the database within MongoDB you wish to use
184 * collection (optional): Specify the collection within the db you wish to use. This is optional and will default to `fs` if not specified
185
186
187 Context returned:
188
189 * None
190
191
192 ### couch.CouchDBUploadBackend ###
193
194 Stores the file in a CouchDB backend
195
196 Requirements
197
198 * [couchdb](http://code.google.com/p/couchdb-python/)
199
200 Settings:
201
202 * `AJAXUPLOAD_COUCHDB_HOST`: Specify the host of your CouchDB server. Defaults to `http://localhost:5984` if not specified.
203
204 Arguments
205
206 * db (required): Specify the database within CouchDB you wish to use
207
208
209 Context returned:
210
211 * None
212
213
214 ### s3.S3UploadBackend ###
215
216 Stores the file in Amazon's S3.
217
218 Requirements:
219
220 * [boto](https://github.com/boto/boto)
221
222 Settings:
223
224 * `NUM_PARALLEL_PROCESSES` : Uploads to Amazon are parallelized to increase speed. If you have more cores and a big pipe, increase this setting for better performance. Defaults to 4.
225 * `BUFFER_SIZE`: The size of each chunk to write. Defaults to 10 MB.
226
227 Context returned:
228
229 * None
230
231
232 ### thumbnail.ThumbnailUploadBackend ###
233
234 Stores a thumbnail of the locally, optionally discarding the upload.  Subclasses `LocalUploadBackend`.
235
236 Requirements:
237
238 * [sorl-thumbnail](https://github.com/sorl/sorl-thumbnail)
239
240 Settings:
241
242 * `DIMENSIONS` : A string of the dimensions (WxH) to resize the uploaded image to. Defaults to "100x100"
243 * `KEEP_ORIGINAL`: Whether to keep the originally uploaded file. Defaults to False.
244 * `BUFFER_SIZE`: The size of each chunk to write. Defaults to 10 MB.
245
246 Context returned:
247
248 * `path`: The full media path to the uploaded file.
249
250
251 ### default_storage.DefaultStorageUploadBackend ###
252
253 This backend uses Django's default storage backend (defined by the  DEFAULT_FILE_STORAGE setting) to save the uploaded files.
254
255 Requirements:
256
257 * None
258
259 Settings:
260
261 * `UPLOAD_DIR` : The directory to store the uploaded file in, within `MEDIA_ROOT`. Defaults to "uploads".
262 * `BUFFER_SIZE`: The size of each chunk to write. Defaults to 10 MB.  See the caveat at the bottom before changing it.
263
264 Context returned:
265
266 * `path`: The full media path to the uploaded file.
267
268
269 Backend Usage
270 ------------------------
271
272 The default backend is `local.LocalUploadBackend`. To use another backend, specify it when instantiating `AjaxFileUploader`.
273
274 For instance, to use `MongoDBUploadBackend`:
275
276 views.py
277
278 ```python
279 from ajaxuploader.views import AjaxFileUploader
280 from ajaxuploader.backends.mongodb import MongoDBUploadBackend
281
282 ...
283 import_uploader = AjaxFileUploader(backend=MongoDBUploadBackend, db='uploads')
284 ```
285
286 To set custom parameters, simply pass them along with instantiation.  For example, for larger thumbnails, preserving the originals:
287 views.py
288
289     from ajaxuploader.backends.thumbnail import ThumbnailUploadBackend
290
291     ...
292     import_uploader = AjaxFileUploader(backend=ThumbnailUploadBackend, DIMENSIONS="500x500", KEEP_ORIGINAL=True)
293
294
295 Custom Backends
296 -------------
297
298 To write a custom backend, simply inherit from `backends.base.AbstractUploadBackend` and implement the `upload_chunk` method.  All possible methods to override are described below.
299
300 * `upload_chunk` - takes a string, and writes it to the specified location.
301 * `setup`: takes the original filename, does all pre-processing needed before uploading the file (for example, for the S3 backend, this method is used to establish a connection with the S3 server).
302 * `update_filename`: takes the `request` object and the original name of the file being updated, can return a new filename which will be used to refer to the file being saved. If undefined, the uploaded filename is used.  If not overriden by `upload_complete`, this value will be returned in the response.
303 * `upload_complete`: receives the `request` object and the filename post `update_filename` and does any cleanup or manipulation after the upload is complete.  (Examples:  cropping the image, disconnecting from the server).  If a dict is returned, it is used to update the response returned to the client.
304
305
306 Caveats
307 =======
308 `BUFFER_SIZE` - some users have reported problems using smaller buffer sizes.  I also saw random failed uploads with very small sizes like 32k.  10MB has been completely reliable for me, and in what I've read here and there, so do some testing if you want to try a different value.  Note that this doesn't have a big impact on the overall upload speed.
309
310
311 Credits
312 =======
313 Original implementation and ongoing maintenance by [skoczen](https://github.com/skoczen), courtesy of [GoodCloud](https://www.agoodcloud.com).  
314 Most of the backend abstraction was written by [chromano](https://github.com/chromano) and [shockflash](https://github.com/shockflash).  
315 MongoDB support and saner defaults by [chrisjones-brack3t](https://github.com/chrisjones-brack3t).  
316 Threadsafe improvements and bugfixes by [dwaiter](https://github.com/dwaiter).  
317 CouchDB support by [paepke](https://github.com/paepke).  
318 Default Storage backend by [fhahn](https://github.com/fhahn).  
319 File number limit in upload by [qnub](https://github.com/qnub).  
320 JSON parsing improvements by [onyxfish](https://github.com/onyxfish).  
321
322 This code began as such a trivial layer on top of [valum's uploader](http://valums.com/ajax-upload/), [boto](https://github.com/boto/boto), and [alex's ideas](http://kuhlit.blogspot.com/2011/04/ajax-file-uploads-and-csrf-in-django-13.html) it's silly.  However, I didn't find any implementations that *just worked*, so hopefully it's useful to someone else.  I also drew from these sources:
323
324 * http://www.topfstedt.de/weblog/?p=558
325 * http://www.elastician.com/2010/12/s3-multipart-upload-in-boto.html
326 * https://github.com/valums/file-uploader
327 * https://github.com/alexkuhl/file-uploader
328
329 Many thanks to all for writing such helpful and readable code!