1

There are a couple of ways you could answer this. I'll gleefully accept a solution with node-upload-progress or an Express/formidable solution that allows for upload progress monitoring (I like both of those but Express's recent drop for formidable support is making my brain explode).

I'm attempting to create a page where files can be uploaded with progress monitoring, along with additional fields related to the file such as title, submitter name, file description etc.

The first partial solution I found was node-upload-progress. It worked great right away. Here's the example code pasted here for reference (I added an extra field I want to get the value for).

app.js

(function() {
    var app = require('http');
    var fs = require('fs');
    var uploadProgress = require('node-upload-progress');
    var uploadHandler = new uploadProgress.UploadHandler;

    uploadHandler.configure(function() {
        this.uploadDir = "" + __dirname + "/uploads";
        this.onEnd = customOnEndHandler;
    });

    function customOnEndHandler(req, res){
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Yay! Upload finished.');
    }

    app.createServer(function(req, res) {
        if (req.url.match(/\/upload\?X\-Progress\-ID=.+/)) {
            console.log('upload started');
            return uploadHandler.upload(req, res);
        } else if (req.url.match(/\/progress\?X\-Progress\-ID=.+/)) {
            return uploadHandler.progress(req, res);
        } else {
            return fs.readFile("" + __dirname + "/index.html", function(err, data) {
                res.writeHead(200, {
                  'Content-Type': 'text/html'
                });
                res.write(data.toString());
                return res.end();
            });
        }
    }).listen(8080);

    console.log('Server running at http://localhost:8080/');

}).call(this);

index.html:

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Test Upload</title>
    <meta name="author" content="Pablo Cantero <pablo@pablocantero.com>">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <!-- Date: 2012-06-12 -->
    <script>
        $(function(){
            var uploadIntervalID;
            $('#form_upload').submit(function(){
                // Preventing multiples clicks on upload
                clearInterval(uploadIntervalID);
                var xProgressID = guidGenerator();
                $(this).attr('action', '/upload?X-Progress-ID=' + xProgressID);
                uploadIntervalID = setInterval(function(){
                    $.get('/progress?X-Progress-ID=' + xProgressID, function(data){
                        if(data.status === 'done'){
                            clearInterval(uploadIntervalID);
                        }
                        updateUploadStatus(data);
                    }).error(function(){clearInterval(uploadIntervalID)});
                }, 250);
                return true;
            });

            function updateUploadStatus(data){
                $('#upload_percent').text(data.percent);
                $('#upload_status').text(data.status);
                $('#upload_filename').text(data.fileName);
                $('#upload_filepath').text(data.filePath);
            }

            // http://stackoverflow.com/a/105074/464685
            function guidGenerator() {
                return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
            }

            function S4() {
                return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
            }
        });
    </script>
</head>
<body>
    <h1>Super Upload</h1>
    <form action="/upload?X-Progress-ID=1" enctype="multipart/form-data" method="post" id="form_upload" target="iframe_upload">
        <p>
            <label>File</label><br/>
            <input type="file" name="upload" id="upload"><br>
            <span id="upload_percent"></span><br/>
            <span id="upload_status"></span><br/>
            <span id="upload_filename"></span><br/>
            <span id="upload_filepath"></span>
        </p>

        <p>
            <div>File Title</div>
            <input name="file-title" type="text" maxlength="120" value="test value" />
        </p>

        <p>
            <input type="submit" value="Upload">
        </p>
    </form>
    <iframe id="iframe_upload" name="iframe_upload"></iframe>
</body>
</html>

When researching further about form parsing, I starting finding that formidable was the thing to use, and it worked great with Express (which was great for delivering the front-end I wanted to create and offered simpler basic authentication to access this)... until Express dropped/is dropping built-in formidable support.

Any good ideas and/or examples on how to work through this? My gut says to stick with node-upload-progress and figure out how to parse additional form values from scratch, so that I can better understand and appreciate the conveniences modules such as Express and formidable offer.

Thanks for helping a node.js new person in advance. :D

Christopher Stevens
  • 1,214
  • 17
  • 32
  • This might be a good answer for parsing incoming post data: http://stackoverflow.com/questions/16685895/how-to-handle-form-data-in-an-http-requests-in-nodejs (which may or may not work great if I'm getting data from a form, uploading a 3GB file...) – Christopher Stevens Apr 17 '14 at 16:45
  • As the gears turn, maybe I get form values (jQuery) and submit those as json with an id that can be associated with the big file upload... – Christopher Stevens Apr 17 '14 at 18:49

0 Answers0