Next Spaceship

Driving into future…

Upload File With HTML5

| Comments

Since HTML5 is currently widely supported, and it’s a standard, it’s time to use it. Users who don’t have a modern browser should have one now. And browsers are free, why not use a faster and more standard one?

Uploading files was not supported by HTML for a long time. For example, you can not post a new file to server via Ajax. Actually you can do this, but in a hack way or with Flash. There is not even an elegent way to do this. But this will not happen any more. Things move forward. We have HTML5 now.

With HTML5, we can implement an uploading file server easily. Let me show you.

First, add this code to your html file.

1
2
3
4
5
6
7
8
9
10
11
12
13
<form id="upload">
    <fieldset>
        <div>
            <div id="filedrag">To append a new image, drop file here!</div>
        </div>
    </fieldset>
</form>
<div class="upload_progress progress progress-striped active" style="display:none">
    <div class="upload_progress_bar progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
        <span class="sr-only">0% Complete</span>
    </div>
</div>
<script type="text/javascript" src="/static/js/filedrag.js"></script>

Second, add the js file filedrag.js you includes in the html file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
filedrag.js - HTML5 File Drag & Drop demonstration
Featured on SitePoint.com
Developed by Craig Buckler (@craigbuckler) of OptimalWorks.net
Modified by Leon(i@leons.im)
*/
(function() {

    // getElementById
    function $id(id) {
        return document.getElementById(id);
    }

    // file drag hover
    function FileDragHover(e) {
        e.stopPropagation();
        e.preventDefault();
        e.target.className = (e.type == "dragover" ? "hover" : "");
    }

    // update the progress bar
     function uploadProgress(evt) {
        if (evt.lengthComputable) {
            var uploaded = Math.round(evt.loaded * 100 / evt.total);
            $(".upload_progress").show();
            $(".upload_progress_bar").attr("style","width:" + uploaded + "%;");
            $(".upload_progress_bar").attr("aria-valuenow", uploaded);
            $(".upload_progress_bar>.sr-only").text(uploaded + '% Completed.');

            //document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
        }
        else {
            //document.getElementById('progressNumber').innerHTML = 'unable to compute';
        }
    }

    // file selection
    function FileSelectHandler(e) {

        // cancel event and hover styling
        FileDragHover(e);

        // fetch FileList object
        var files = e.target.files || e.dataTransfer.files;

        // init the ajax request
        var xhr = new XMLHttpRequest();
        var url = window.location.href.toString();
        var filepath = '/upload';

        xhr.open('post', filepath, true);
        xhr.upload.addEventListener("load", uploadProgress, false);
        xhr.upload.addEventListener("progress", uploadProgress, false);
        xhr.onload = function(e) {

            if (this.status == 200) {
                var url = this.response;
                $('<img src="' + url + '" class="img-responsive new-img">').insertBefore('#filedrag');
                //alert(this.response);
                $('.upload_progress').hide();
            }
            else {
                alert('Failed.');
            }
        }

        var formData = new FormData();

        // process all File objects
        for (var i = 0, f; f = files[i]; i++) {
            formData.append('file', f);
        }
        xhr.send(formData);
    }

    // initialize
    function Init() {

        var filedrag = $id("filedrag");

        // is XHR2 available?
        var xhr = new XMLHttpRequest();
        if (xhr.upload) {

            // file drop
            filedrag.addEventListener("dragover", FileDragHover, false);
            filedrag.addEventListener("dragleave", FileDragHover, false);
            filedrag.addEventListener("drop", FileSelectHandler, false);
            filedrag.style.display = "block";
        }
    }

    // call initialization file
    if (window.File && window.FileList && window.FileReader) {
        Init();
    }
})();

At last, implement the server side. For instance, this is a Python code in Tornado Framework.

1
2
3
4
5
6
7
8
9
10
11
12
13
import logging
from tornado.web import RequestHandler

class MainHandler(RequestHandler):
    def post(self):
        if 'file' in self.request.files:
            f = self.request.files['file'][0]
            f_data = f['body']
            f_type = f['filename'].split('.')[-1]
            f_url = self.img_root + data_file.save(self.root, f_data, f_type)

            logging.info('f_url = %s' % f_url)
            self.write(f_url);

Here, you need to implement data_file.save() method by yourself.

Done.

Comments