Bachalo
Bachalo

Reputation: 7219

AIR, URLRequest and uploading video file to NodeJS server

I have a NodeJS server set up on localhost (for testing) that I am using to run FFMPEG on video files that are uploaded. This is the actual node application I am uploading to.
https://github.com/madebyhiro/codem-transcode
The actual conversion process works correctly if I run a curl job in the OSX console using

sudo curl -d '{"source_file": "MASTER.flv","destination_file":"converted.mp4","encoder_options": "-vcodec libx264 -vb 416k -s 320x180 -y -threads 0"}' http://localhost:8080/jobs

so I know the node server is running properly.

You can see that a specific JSON object is required as part of the HTTP POST request. (In my AIR client code sample below this is the params Object which I have intentionally left blank.)

On the client side I am using a AIR for desktop application to simply upload the video files.

Many Questions

  1. Is a primary issue simply that you cannot upload files on the same machine to a local server?

  2. Am I missing something from my requestHeaders?

  3. Should I be using contentType = "multipart/form-data" or some other contentType?
  4. Should contentType be part of the headers as I've done or defined as a property on the actual UrlRequest Object?
  5. Should I be using UrlLoader.load instead of File.upload?
  6. Is file.url formatted properly (assuming my str value is correct)?
  7. Any other errors or omissions in my uploadFile code method below?

I am rewarding a large bounty but only if ALL the above questions have been accurately answered, with preference given to answers with references or a code sample. Here is another related question with some useful information POST file upload using URLRequest

Here is the relevant upload code. str is the nativePath to the actual video file I am uploading. As previously mentioned the JSON params Object has been intentionally left blank, so would need proper formatting for it to work properly.

function uploadFile(str:String):void {
            var params:Object={}
            var jsonOb:String = JSON.stringify(params);
            var hdr:URLRequestHeader = new URLRequestHeader("Content-type", "application/json");
            var request:URLRequest=new URLRequest("http://localhost:8080");
            request.requestHeaders.push(hdr);
            request.method=URLRequestMethod.POST;
            request.useCache=false;
            request.cacheResponse=false;
            //pass urlVariables instead of JSON Object??
            request.data=jsonOb;

            var file:File=new File();
            configureListeners(file);
            file.url='file:///'+str;

            try {
                file.upload(request);
            } catch (e:Error) {
                trace('error', e);
            }

        }

        private function configureListeners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(ProgressEvent.PROGRESS, uploadProgressHandler, false, 0, false);
            dispatcher.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, httpResponseHandler, false, 0, false);
            dispatcher.addEventListener(Event.COMPLETE, uploadCompleteHandler, false, 0, true);
            dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler, false, 0, true);
            dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false, 0, true);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
        }

Upvotes: 1

Views: 1663

Answers (1)

Wouter Verweirder
Wouter Verweirder

Reputation: 606

  1. Nope, you can upload files to any server, doesn't matter if it's local or online
  2. You didn't forget any headers. In matter of fact, file.upload will correct your content-type header to multipart/form-data and set the correct boundary
  3. See 2.
  4. See 2.
  5. No, file.upload can work just fine
  6. Format is correct
  7. Well, you should send the JSON data as URLVariables for the extra data to work. Otherwise file.upload will ignore that data and overwrite it with the file itself.

This is the code I tested, and works here:

Actionscript Code: (also added a UPLOAD_COMPLETE_DATA listener, to get nodejs response on upload)

uploadFile("/Users/wouter/test.jpg");

private function uploadFile(str:String):void {
    //additional data needs to be a URLVariables instance
    var data:URLVariables = new URLVariables();
    data.origFile = str;
    //no use, upload will reset headers
    //var hdr:URLRequestHeader = new URLRequestHeader("Content-type", "application/json");
    var request:URLRequest=new URLRequest("http://localhost:8080");
    //request.requestHeaders.push(hdr);
    request.method=URLRequestMethod.POST;
    request.useCache=false;
    request.cacheResponse=false;
    //pass urlVariables instead of JSON Object??
    request.data=data;

    var file:File=new File();
    configureListeners(file);
    file.url='file:///'+str;

    try {
        file.upload(request);
    } catch (e:Error) {
        trace('error', e);
    }

}

private function configureListeners(dispatcher:IEventDispatcher):void {
    dispatcher.addEventListener(ProgressEvent.PROGRESS, uploadProgressHandler, false, 0, false);
    dispatcher.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, httpResponseHandler, false, 0, false);
    dispatcher.addEventListener(Event.COMPLETE, uploadCompleteHandler, false, 0, true);
    dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler, false, 0, true);
    dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false, 0, true);
    dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
    //add a UPLOAD_COMPLETE_DATA event to process server response
    dispatcher.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadDataComplete, false, 0, true);
}

NodeJS Server (using express 4.0 and multer 0.1.7 to handle file uploads):

var express = require('express'),
    multer  = require('multer');
var app = express();

//auto save file to uploads folder
app.use(multer({ dest: './uploads/'}))

app.post('/', function (req, res) {
    console.log(req.body); //contains the variables
    console.log(req.files); //contains the file references
    res.send('Thank you for uploading!');
});

app.listen(8080);

Upvotes: 2

Related Questions