upload: Add form to upload images

The upload form allows users to upload images to the Dark Chest of
Wonders screenshot gallery. No authentication, etc. is performed, so
this needs to be handled by the web server.
master
Dustin 2017-07-02 11:37:46 -05:00
parent 65f1a46d17
commit ab5a41f686
4 changed files with 128 additions and 0 deletions

View File

@ -3,6 +3,7 @@ from . import (
base, base,
gallery, gallery,
thumbnails, thumbnails,
upload,
) )
import functools import functools
import logging import logging
@ -40,6 +41,7 @@ class Application(milla.Application):
r.add_route('/', gallery.GalleryController()) r.add_route('/', gallery.GalleryController())
r.add_route('/thumbnails/{image}', thumbnails.ThumbnailController()) r.add_route('/thumbnails/{image}', thumbnails.ThumbnailController())
r.add_route('/upload', upload.UploadController())
def make_request(self, environ): def make_request(self, environ):
request = super(Application, self).make_request(environ) request = super(Application, self).make_request(environ)

View File

@ -18,6 +18,11 @@
</div> </div>
{% block body %} {% block body %}
{% endblock body -%} {% endblock body -%}
{% block script -%}
<script
src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
{% endblock script -%}
</body> </body>
</html> </html>

View File

@ -0,0 +1,75 @@
{% extends "base.html.j2" %}
{% block head -%}
{{ super() }}
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/blueimp-file-upload/9.18.0/css/jquery.fileupload.min.css" />
{% endblock head %}
{% block body -%}
<div class="row column">
<form enctype="multipart/form-data" method="post">
<span id="select-file">
<input type="file" id="fileupload" name="file" accept=".png,.jpg,.jpeg,.bmp" />
</span>
<div id="submit-button">
<button type="submit" class="button">Submit</button>
</div>
<div id="progress" class="progress hide">
<div class="progress-meter" style="width: 0;"></div>
</div>
</form>
</div>
<div class="row column">
<span id="results" class="form-error{{ ' is-visible' if error is defined }}">
{%- if error is defined %}
{{ error.message }}
{% endif -%}
</span>
</div>
{% endblock body -%}
{% block script -%}
{{ super() }}
<script
src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js">
</script>
<script
src="//cdnjs.cloudflare.com/ajax/libs/blueimp-file-upload/9.18.0/js/jquery.iframe-transport.min.js">
</script>
<script
src="//cdnjs.cloudflare.com/ajax/libs/blueimp-file-upload/9.18.0/js/jquery.fileupload.min.js">
</script>
<script>
/* <![CDATA[ */
$('#select-file').addClass('button fileinput-button')
.append('<span>Select File…</span>');
$('#submit-button').addClass('hide');
$('#progress').removeClass('hide');
$('#fileupload').fileupload({
url: '',
dataType: 'json',
submit: function(e, data) {
$('#progress .progress-meter').css('width', '0')
$('#progress').removeClass('alert success');
$('#results').removeClass('is-visible').text('');
},
done: function(e, data) {
$('#progress').addClass('success');
window.location = '..';
},
fail: function(e, data) {
$('#progress').addClass('alert');
var error;
try {
error = data.jqXHR.responseJSON.error.message;
} catch (e) {
error = data.errorThrown;
}
$('#results').addClass('is-visible').text(error);
},
progressall: function(e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-meter').css('width', progress + '%');
}
});
/* ]]> */
</script>
{% endblock script -%}

46
src/dcow/upload.py Normal file
View File

@ -0,0 +1,46 @@
from . import gallery
import errno
import milla.controllers
import os
class UploadController(milla.controllers.HTTPVerbController):
def GET(self, request):
# XXX blueimp jQuery File Upload plugin does not work in XML parser
request.want = 'html'
response = request.ResponseClass()
response.set_payload('upload.html.j2')
return response
def POST(self, request):
screenshot_dir = request.config['gallery.screenshot_dir']
f = request.POST['file']
path = os.path.join(screenshot_dir, f.filename)
try:
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
except (IOError, OSError) as e:
if e.errno == errno.EEXIST:
response = request.ResponseClass()
response.status_int = milla.HTTPConflict.code
response.set_payload('upload.html.j2', {
'error': {
'message':
'Image {} already exists'.format(f.filename),
'code': response.status_int,
}
})
return response
else:
raise milla.HTTPServerError(
'{}'.format(e),
)
else:
with os.fdopen(fd, 'wb') as q:
for d in iter(lambda: f.file.read(4096), b''):
q.write(d)
if request.want == 'json':
raise milla.HTTPCreated
else:
raise milla.HTTPSeeOther(location='/')