The Panda uploader allows you to upload videos from your web application to Panda. It's an HTML5 uploader solution with Flash fallback.

Here is a couple of features that forced us to rewrite the uploader from scratch.
We highly recommended that you use the CDN hosted minified version of the uploader library. You can keep up to date automatically with patch releases by linking to a minor version. The current stable version is 2.0. To do so, simply include the following declaration in your page:
<script src="//cdn.pandastream.com/u/2.0/panda-uploader.min.js"></script>
By invoking panda.uploader.init(options) with a set of configuration options, you will initialize the Panda uploader
Here is the list of options available at the time of initialization:
buttonId: Dom Id of the styled Browsing button.
( required!, it should be a <div> )
authorizeUrl: Route of the authentication request.
( example: /panda/authorize_upload )
autoStart: Upload starts right after the user select a file.
( true/false, default: true )
autoResume: Automatically resume the upload after you went offline.
( true/false, default: true )
resumeInterval: Interval in milliseconds before the upload gets resumed.
( default: 5000 )
allowSelectMultipleFiles: Allows you to add multiple files to the upload queue.
( true/false, default: false )
progressBarId: Dom id of the progress bar.
fileDropId: Dom id of the file drop zone.
maxFileSize: Maximun file size.
( example: '10 MB', valid: [K|M|G]B, default: null )
confirmBeforeUnload: Alert the user that an upload is processing.
( true/false, default: true )
type: Forces the uploader type.
( html/flash, default null )
onQueue (files): List of <files> added to the Queue.
onStart (file): <file> starts uploading.
onProgress (file, percent): <file> upload progress.
onSuccess (file, json): The uploader has successfully uploaded <file> and returned a <json> object.
onError (file, text): The uploader has failed uploading <file> and returned a response.
onComplete (): The upload queue has been completed.
onCancel (file): <file> upload has been canceled.
onPause (file): <file> upload has been paused due to connectivity issues.
<Uploader> Object:
type: Returns the uploader type (html5/flash).
setPayload (file, object): Add extra variables to the payload.
setEnabled (bool): Enable/Disable the uploader.
getQueuedFiles (): Returns the list of queued files.
start (): Start uploading next queued file.
cancel (file): cancel <file> upload.
<File> Objet:
name: File name.
size: File size in Bytes.
The authentication of your new upload occurs via an HTTP Request to a configurable authentication url when the file is ready to be uploaded. In the JavaScript Uploader the HTTP Request is executed via AJAX POST request.
The destination of the authentication request can be configured by setting the authorizeUrl param when calling panda.uploader.init.
The default is /panda/authorize_upload
A playload is then sent as a JSON encoded object in the body containing the following variables filesize, filename, content_type.
These should be self-explanatory.
Here are some examples of upload authentication for different languages:
# Using Rails and https://github.com/pandastream/panda_gem
# app/controllers/panda_controller.rb
class PandaController < ApplicationController
def authorize_upload
payload = JSON.parse(params['payload'])
upload = Panda.post('/videos/upload.json', {
file_name: payload['filename'],
file_size: payload['filesize'],
profiles: "h264,webm",
# payload: 'something',
# path_format: ':video_id/:profile/play',
})
render :json => {:upload_url => upload['location']}
end
end
# Using Django and https://github.com/pandastream/panda_client_python
# views.py
@csrf_exempt
def authorize_upload(request):
params = json.loads(request.POST['payload'])
upload = panda.post("/videos/upload.json", {
"file_name": params['filename'],
"file_size": params['filesize'],
"profiles": "h264",
})
auth = {"upload_url": json.loads(upload)["location"]}
return HttpResponse(json.dumps(auth), mimetype='application/json')
<?php
// authorize_upload.php
$payload = json_decode($_POST['payload']);
$filename = $payload->{'filename'};
$filesize = $payload->{'filesize'};
$upload = json_decode(@$panda->post("/videos/upload.json",
array('file_name' => $filename, 'file_size' => $filesize, 'profiles' => 'h264')));
$response = array('upload_url' => $upload->location);
header('Content-Type: application/json');
echo json_encode($response);
?>
The api request to Panda should include: file_name and file_size.
Optionally, you can set:
use_all_profiles: (true / false) Default is false
profiles: Comma-separated list of profile names.
By default no encodings are created yet.
payload: Arbitrary string stored along the Video object.
path_format: Allows you to set the location inside your S3 Bucket.
It should not include the file extention.
More details on the api docs
The generated JSON should include:
upload_url Location where to upload the file
postprocess_url (optional) When a file upload is complete, a request is made to this url to let your server know that the uploader finished uploading the file
The following is the simplest working form that will upload a video:
<form action="/path/to/action" id="new_video" method="POST">
<input type="hidden" name="panda_video_id"/>
<div id="browse-files">Choose file</div>
</form>
Uploader setup
var upl = panda.uploader.init({
'buttonId': 'browse-files',
'onProgress': function(file, percent) {
console.log("progress", percent, "%");
},
'onSuccess': function(file, data) {
$("#new_video")
.find("[name=panda_video_id]")
.val(data.id)
.end()
.submit();
},
'onError': function(file, message) {
console.log("error", message);
},
});
In this example:
If you need to, you can add some extra data to the payload alongside the ones mentioned above.
var upl = panda.uploader.init({
...
'onQueue': function(files) {
$.each(files, function(i, file) {
upl.setPayload(file, {'authenticity_token': AUTH_TOKEN});
})
},
}
The uploader comes with some handy handlers like Progress Bars and File Drop.
<form action="/path/to/action" id="new_video" method="POST">
<input type="hidden" name="panda_video_id"/>
<div class='progress'><span id="progress-bar" class='bar'></span></div>
<div id="file-drop">Drop files here</div>
<div id="browse-files">Choose file</div>
</form>
Uploader setup
var upl = panda.uploader.init({
...
'progressBarId': "progress-bar",
'fileDropId': "file-drop",
});
The uploader doesn't come with any styling. Take a look at Twitter Bootstrap
If you have been disconnected from the Internet while you were uploading a file you will be notified by the onPause callback.
It's important to note that the Flash uploader doesn't support this feature so the upload will fail.
By default, the uploader will setup a resume interval of 5 seconds.
You can also create a resume button.
To resume your uploading queue, just call the start method and your current upload will continue where it left off.
var upl = panda.uploader.init({
...
'autoResume': false,
'onPause': function(){
$("#notice").text("You went offline.");
}
})
$("#resume-btn").click(function() {
upl.start();
})
If you want to abort an upload that is currently taking place, use the cancel() function from the uploader instance:
$("#cancel-btn").click(function() {
upl.cancel(file);
})
An aborted upload is no longer resumable.
You might want to let your server know that the uploader finished uploading a file. This is quite useful when handling multiple uploads on a single web page.
To achieve this, you simply need to return the postprocess_url during the authentication handshake.
# app/controllers/panda_controller.rb
class PandaController < ApplicationController
def authorize_upload
...
render :json => {
:upload_url => upload['location'],
:postprocess_url => '/some/postprocess'
}
end
end
# views.py
def authorize_upload(request):
...
auth = {
"upload_url": json.loads(upload)["location"],
"postprocess_url": '/some/postprocess',
}
return HttpResponse(json.dumps(auth), mimetype='application/json')
<?php
// authorize_upload.php
$response = array(
'upload_url' => $upload->location},
'postprocess_url' => 'postprocess.php'
);
header('Content-Type: application/json');
echo json_encode($response);
?>
Once the video is successfully uploaded to Panda, your server will receive a POST request like this.
# app/controllers/some_controller.rb
class SomeController < ApplicationController
def postprocess
response = JSON.parse(params["upload_response"])
render :json => { :id => "some-id" }
end
end
# views.py
@csrf_exempt
def postprocess(request):
response = json.loads(request.POST['upload_response'])
return HttpResponse(json.dumps({"id": "some-id"}), mimetype='application/json')
<?php
// postprocess.php
$response = json_decode($_POST['upload_response']);
header('Content-Type: application/json');
echo json_encode(array('id' => 'some-id'));
?>
The onSuccess callback will expose the data received from the postprocess request.
var upl = panda.uploader.init({
...
'onSuccess': function(file, data) {
console.log(data['id']); // 'some-id'
}
})
The Panda Uploader will use HTML5 upload if the browser supports it, and will fall back to Flash upload if necessary. Flash doesn't have resumable capabilities and will upload your content as a MultiPart stream.
| Browser | Upload Supported? | Method Used |
|---|---|---|
| Opera | Yes | HTML5 |
| Safari | Yes | HTML5 |
| Chrome | Yes | HTML5 |
| Firefox >= 3.5 | Yes | HTML5 |
| IE 6-9 | Yes | Flash |
| Others | Yes | Flash |