"Upload file input"

This commit is contained in:
Doug Le Tough 2017-12-02 01:06:13 +01:00
parent bcb80405be
commit ee4727dde1
13 changed files with 178 additions and 18 deletions

View File

@ -1,2 +1,3 @@
SQLALCHEMY_TRACK_MODIFICATIONS = True SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_DATABASE_URI = "postgresql://tetawebapp:tetawebapp@localhost/tetawebapp" SQLALCHEMY_DATABASE_URI = "postgresql://tetawebapp:tetawebapp@localhost/tetawebapp"
UPLOADED_FILES_DEST = "./upload"

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

View File

@ -4,6 +4,9 @@ var light_red = "#FCD5DC";
var light_green = "#D5FCD8"; var light_green = "#D5FCD8";
var base_bg = "#FFFFFF"; var base_bg = "#FFFFFF";
var base_border = "#888888"; var base_border = "#888888";
var coloured_bg = "#FF5D00";
var clear_bg = "#E5E5E5";
var text_color = "#555555";
/* ************************************************************************************** /* **************************************************************************************
* GLOBAL * GLOBAL
@ -26,6 +29,17 @@ function getcookie(cname) {
} }
// Eye candies // Eye candies
function valid_input(obj) {
// Valid input makes obj background to glow green for 2 seconds
// If obj borders were red, they get they normal color back
obj.style.backgroundColor = light_green;
obj.style.borderColor = base_border;
setTimeout( function() {
obj.style.backgroundColor = base_bg;
}
, 2000);
}
function invalid_input(obj) { function invalid_input(obj) {
// Invalid input makes obj borders and background to glow red for 2 seconds // Invalid input makes obj borders and background to glow red for 2 seconds
// Border color will stay red until a valid input is sent // Border color will stay red until a valid input is sent
@ -37,17 +51,48 @@ function invalid_input(obj) {
, 2000); , 2000);
} }
function valid_input(obj) { function valid_upload(obj) {
// Valid input makes obj background to glow green for 2 seconds // Valid input makes obj background to glow green for 2 seconds
// If obj borders were red, they get they normal color back // If obj borders were red, they get they normal color back
obj.style.backgroundColor = light_green; obj.style.backgroundColor = green;
obj.style.borderColor = base_border; obj.style.borderColor = text_color;
obj.style.borderStyle = 'solid';
setTimeout( function() { setTimeout( function() {
obj.style.backgroundColor = base_bg; obj.style.backgroundColor = clear_bg;
obj.style.borderStyle = 'none';
} }
, 2000); , 2000);
} }
function invalid_upload(obj) {
// Invalid input makes obj borders and background to glow red for 2 seconds
// Border color will stay red until a valid input is sent
obj.style.backgroundColor = red;
obj.style.borderColor = text_color;
obj.style.borderStyle = 'solid';
setTimeout( function() {
obj.style.borderStyle = 'solid';
obj.style.backgroundColor = clear_bg;
obj.style.borderColor = red;
}
, 2000);
}
function lit(obj) {
// Lit bacground and border on obj (use by input type=file)
obj.style.backgroundColor = coloured_bg;
obj.style.borderColor = text_color;
obj.style.borderStyle = 'solid';
}
function unlit(obj) {
// Unlit bacground and border on obj (use by input type=file)
obj.style.backgroundColor = clear_bg;
obj.style.borderColor = clear_bg;
obj.style.borderStyle = 'none';
}
function verify_login() { function verify_login() {
// Verify login inputs // Verify login inputs
login = document.getElementById('login'); login = document.getElementById('login');
@ -140,7 +185,7 @@ function get_value_from_ajax(obj, url, err_code) {
xhttp.onload = function(){ xhttp.onload = function(){
if (xhttp.status != 200) { if (xhttp.status != 200) {
invalid_input(obj); invalid_input(obj);
} }
}; };
xhttp.onreadystatechange = function() { xhttp.onreadystatechange = function() {
@ -156,6 +201,44 @@ function get_value_from_ajax(obj, url, err_code) {
} }
}; };
xhttp.open('POST', url, true); xhttp.open('POST', url, true);
alert(xhttp.readyState);
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send(); xhttp.send();
} }
function upload_file_from_ajax(obj, url, err_code) {
// Upload files get from <obj> to the specified <url>
// if <errcode> is returned input is invalidated
var files = obj.files;
var icon_id = obj.id.substring(obj.id.lastIndexOf("_") + 1);
var icon_obj = document.getElementById("upload_icon_" + icon_id)
var xhttp = new XMLHttpRequest();
xhttp.onerror = function(){
invalid_upload(icon_obj);
};
xhttp.onload = function(){
if (xhttp.status != 200) {
invalid_upload(icon_obj);
}
};
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var response = xhttp.responseText;
if (response == err_code) {
invalid_upload(icon_obj);
return;
}
valid_upload(icon_obj);
return;
}
};
xhttp.open('POST', url, true);
var formData = new FormData();
for (var i=0; i < files.length; i++){
formData.append("files", files[i], files[i].name);
}
xhttp.send(formData);
}

View File

@ -25,4 +25,5 @@
--save_icon: url(/static/images/save.png); --save_icon: url(/static/images/save.png);
--search_icon: url(/static/images/search.png); --search_icon: url(/static/images/search.png);
--trash_icon: url(/static/images/trash.png); --trash_icon: url(/static/images/trash.png);
--upload_icon: url(/static/images/upload.png);
} }

View File

@ -254,12 +254,36 @@ input[type="submit"] {
button:hover, button:hover,
input[type="button"]:hover, input[type="button"]:hover,
input[type="submit"]:hover { input[type="submit"]:hover,
input[type="file"]:hover {
background-color: var(--light-coloured-bg); background-color: var(--light-coloured-bg);
color: var(--text-color); color: var(--text-color);
cursor: pointer; cursor: pointer;
} }
div.file_upload {
display: inline-block;
position: relative;
width: 20px;
height: 20px;
margin: 0;
padding: 0;
border-radius: 2px;
border-style: solid;
border-width: 1px;
border-color: var(--clear-bg);
}
input[type="file"] {
position: absolute;
width: 18px;
height: 18px;
left: 0;
top: 1px;
opacity: 0;
}
input.add, input.add,
input.edit, input.edit,
input.login, input.login,
@ -267,7 +291,8 @@ input.logout,
input.refresh, input.refresh,
input.save, input.save,
input.search, input.search,
input.trash { input.trash,
input.upload {
width: 20px; width: 20px;
height: 20px; height: 20px;
margin: 0; margin: 0;
@ -283,7 +308,8 @@ input.logout:hover,
input.refresh:hover, input.refresh:hover,
input.save:hover, input.save:hover,
input.search:hover, input.search:hover,
input.trash:hover { input.trash:hover,
input.upload:hover {
border-color: var(--text-color); border-color: var(--text-color);
border-style: solid; border-style: solid;
border-width: 1px; border-width: 1px;
@ -331,3 +357,8 @@ input.trash {
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
} }
input.upload {
background: var(--upload_icon);
background-repeat: no-repeat;
background-position: center center;
}

View File

@ -25,4 +25,16 @@
<input type='button' value="Try me" onclick='javascript:get_value_from_ajax(document.getElementById("value_receiver"), "/get_value_from_ajax", "TETA_ERR");'> <input type='button' value="Try me" onclick='javascript:get_value_from_ajax(document.getElementById("value_receiver"), "/get_value_from_ajax", "TETA_ERR");'>
</article> </article>
</section> </section>
<article class='left'>
<h3>Upload files with AJAX</h3>
<p>Select files to upload</p>
<p>The response may randomly be an error response so you should try it more than once.</p>
<div class='file_upload'>
<!--
Input file is a tricky hack (see tetawebapp.css and tetawebapp.js)
-->
<input type='button' id='upload_icon_1' class='upload' title='Upload' value=' '/>
<input type='file' id='upload_input_1' multiple title='Upload' value='' onchange='javascript:upload_file_from_ajax(this, "/upload", "TETA_ERR");' onmouseover='javascript:lit(document.getElementById("upload_icon_1"));' onmouseout='javascript:unlit(document.getElementById("upload_icon_1"));'/>
</div>
</article>
{% endblock %} {% endblock %}

View File

@ -20,14 +20,21 @@
<br/> <br/>
<input type='button' value='And me !' /> <input type='button' value='And me !' />
<br/> <br/>
<input type='button' class='add' title='add' value=' '/> <input type='button' class='add' title='Add' value=' '/>
<input type='button' class='edit' title='edit' value=' '/> <input type='button' class='edit' title='Edit' value=' '/>
<input type='button' class='login' title='login' value=' '/> <input type='button' class='login' title='Login' value=' '/>
<input type='button' class='logout' title='logout' value=' '/> <input type='button' class='logout' title='Logout' value=' '/>
<input type='button' class='refresh' title='refresh' value=' '/> <input type='button' class='refresh' title='Refresh' value=' '/>
<input type='button' class='save' title='save' value=' '/> <input type='button' class='save' title='Save' value=' '/>
<input type='button' class='search' title='search' value=' '/> <input type='button' class='search' title='Search' value=' '/>
<input type='button' class='trash' title='trash' value=' '/> <input type='button' class='trash' title='Trash' value=' '/>
<!--
Input file is a tricky hack (see tetawebapp.css and tetawebapp.js)
-->
<div class='file_upload'>
<input type='button' id='upload_icon_1' class='upload' title='Upload' value=' '/>
<input type='file' id='upload_input_1' name='files' multiple title='Upload' value='' onchange='javascript:upload_file_from_ajax(this, "/upload", "TETA_ERR");' onmouseover='javascript:lit(document.getElementById("upload_icon_1"));' onmouseout='javascript:unlit(document.getElementById("upload_icon_1"));'/>
</div>
<br/> <br/>
<pre> <pre>
#!/bin/sh #!/bin/sh

View File

@ -224,7 +224,7 @@ def get_html_from_ajax():
""" Return HTML code to an AJAX request """ Return HTML code to an AJAX request
It may generate a 404 http error for testing purpose """ It may generate a 404 http error for testing purpose """
if int(random.random()*10) % 2: if int(random.random()*10) % 2:
# Randomlu generate 404 HTTP response # Randomly generate 404 HTTP response
return render_template('error.html'), 404 return render_template('error.html'), 404
return render_template('ajax_html.html') return render_template('ajax_html.html')
@ -236,7 +236,7 @@ def get_value_from_ajax():
err_code = 'TETA_ERR' err_code = 'TETA_ERR'
RND = int(random.random()*10) RND = int(random.random()*10)
if RND % 2: if RND % 2:
# Randomlu generate error # Randomly generate error
return err_code return err_code
return str(RND) return str(RND)
@ -250,6 +250,31 @@ def set_value_from_ajax(value):
return 'True' return 'True'
return err_code return err_code
@app.route("/upload", methods=['POST'])
@check_session
def upload():
""" Accept a value from an AJAX request
It may return an error code for testing purpose """
err_code = 'TETA_ERR'
RND = int(random.random()*10)
if RND % 2:
# Randomly generate error
print err_code
return err_code
uploaded_files = []
if len(request.files) > 0 and request.files['files']:
uploaded_files = request.files.getlist("files")
print "Uploaded files:"
for f in uploaded_files:
print ' [+] %s [%s]' % (f.filename, f.content_type)
# Befor saving you should:
# - Secure the filename
# - Check file size
# - Check content type
f.save(os.path.join(app.config['UPLOADED_FILES_DEST'], f.filename))
f.close()
return "OK"
######################################################################## ########################################################################
# Main # Main
######################################################################## ########################################################################

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.