mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-19 08:33:24 +02:00
Show upload/processing progress for normal file uploads.
This commit is contained in:
@@ -3,6 +3,7 @@ var util = require('util')
|
||||
var fs = require('fs')
|
||||
|
||||
var express = require('express')
|
||||
var validator = require('express-validator')
|
||||
var formidable = require('formidable')
|
||||
var Promise = require('bluebird')
|
||||
var ApkReader = require('adbkit-apkreader')
|
||||
@@ -34,6 +35,9 @@ module.exports = function(options) {
|
||||
app.set('case sensitive routing', true)
|
||||
app.set('trust proxy', true)
|
||||
|
||||
app.use(express.json())
|
||||
app.use(validator())
|
||||
|
||||
storage.on('timeout', function(id) {
|
||||
log.info('Cleaning up inactive resource "%s"', id)
|
||||
})
|
||||
@@ -125,105 +129,114 @@ module.exports = function(options) {
|
||||
}
|
||||
|
||||
app.post('/api/v1/resources', function(req, res) {
|
||||
function handle(fields, files) {
|
||||
var seq = 0
|
||||
var seq = 0
|
||||
|
||||
function sendProgress(data, progress) {
|
||||
if (fields.channel) {
|
||||
push.send([
|
||||
fields.channel
|
||||
, wireutil.envelope(new wire.TransactionProgressMessage(
|
||||
options.id
|
||||
, seq++
|
||||
, data
|
||||
, progress
|
||||
))
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
function sendDone(success, data, body) {
|
||||
if (fields.channel) {
|
||||
push.send([
|
||||
fields.channel
|
||||
, wireutil.envelope(new wire.TransactionDoneMessage(
|
||||
options.id
|
||||
, seq++
|
||||
, success
|
||||
, data
|
||||
, body ? JSON.stringify(body) : null
|
||||
))
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
if (files.file) {
|
||||
return processFile(files.file)
|
||||
.progressed(function(progress) {
|
||||
sendProgress('processing', 0.9 * progress.percent)
|
||||
})
|
||||
.then(function(manifest) {
|
||||
sendProgress('storing', 90)
|
||||
return storeFile(files.file)
|
||||
.then(function(data) {
|
||||
data.manifest = manifest
|
||||
sendDone(true, 'success', data)
|
||||
return data
|
||||
})
|
||||
})
|
||||
.catch(function(err) {
|
||||
sendDone(false, err.reportCode || 'fail')
|
||||
return Promise.reject(err)
|
||||
})
|
||||
}
|
||||
else if (fields.url) {
|
||||
return download(fields.url)
|
||||
.progressed(function(progress) {
|
||||
sendProgress('uploading', 0.7 * progress.percent)
|
||||
})
|
||||
.then(function(file) {
|
||||
return processFile(file)
|
||||
.progressed(function(progress) {
|
||||
sendProgress('processing', 70 + 0.2 * progress.percent)
|
||||
})
|
||||
.then(function(manifest) {
|
||||
sendProgress('storing', 90)
|
||||
return storeFile(file)
|
||||
.then(function(data) {
|
||||
data.manifest = manifest
|
||||
sendDone(true, 'success', data)
|
||||
return data
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch(function(err) {
|
||||
sendDone(false, err.reportCode || 'fail')
|
||||
return Promise.reject(err)
|
||||
})
|
||||
}
|
||||
else {
|
||||
throw new requtil.ValidationError('"file" or "url" is required')
|
||||
function sendProgress(data, progress) {
|
||||
if (req.query.channel) {
|
||||
push.send([
|
||||
req.query.channel
|
||||
, wireutil.envelope(new wire.TransactionProgressMessage(
|
||||
options.id
|
||||
, seq++
|
||||
, data
|
||||
, progress
|
||||
))
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
var form = Promise.promisifyAll(new formidable.IncomingForm())
|
||||
form.parseAsync(req)
|
||||
.spread(handle)
|
||||
function sendDone(success, data, body) {
|
||||
if (req.query.channel) {
|
||||
push.send([
|
||||
req.query.channel
|
||||
, wireutil.envelope(new wire.TransactionDoneMessage(
|
||||
options.id
|
||||
, seq++
|
||||
, success
|
||||
, data
|
||||
, body ? JSON.stringify(body) : null
|
||||
))
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
requtil.validate(req, function() {
|
||||
req.checkQuery('channel').notEmpty()
|
||||
})
|
||||
.then(function() {
|
||||
if (req.is('application/json')) {
|
||||
return requtil.validate(req, function() {
|
||||
req.checkBody('url').notEmpty()
|
||||
})
|
||||
.then(function() {
|
||||
return download(req.body.url)
|
||||
.progressed(function(progress) {
|
||||
sendProgress('uploading', 0.7 * progress.percent)
|
||||
})
|
||||
})
|
||||
}
|
||||
else {
|
||||
var form = Promise.promisifyAll(new formidable.IncomingForm())
|
||||
function progressListener(received, expected) {
|
||||
if (expected) {
|
||||
sendProgress('uploading', 70 * (received / expected))
|
||||
}
|
||||
}
|
||||
sendProgress('uploading', 0)
|
||||
form.on('progress', progressListener)
|
||||
return form.parseAsync(req)
|
||||
.finally(function() {
|
||||
form.removeListener('progress', progressListener)
|
||||
})
|
||||
.spread(function(fields, files) {
|
||||
if (!files.file) {
|
||||
throw new requtil.ValidationError('validation error', [
|
||||
{
|
||||
"param": "file"
|
||||
, "msg": "Required value"
|
||||
}
|
||||
])
|
||||
}
|
||||
return files.file
|
||||
})
|
||||
}
|
||||
})
|
||||
.then(function(file) {
|
||||
return processFile(file)
|
||||
.progressed(function(progress) {
|
||||
sendProgress('processing', 70 + 0.2 * progress.percent)
|
||||
})
|
||||
.then(function(manifest) {
|
||||
sendProgress('storing', 90)
|
||||
return storeFile(file)
|
||||
.then(function(data) {
|
||||
data.manifest = manifest
|
||||
return data
|
||||
})
|
||||
})
|
||||
})
|
||||
.then(function(data) {
|
||||
sendDone(true, 'success', data)
|
||||
data.success = true
|
||||
res.json(201, data)
|
||||
})
|
||||
.catch(requtil.ValidationError, function() {
|
||||
res.json(400, {
|
||||
success: false
|
||||
, error: 'ValidationError'
|
||||
})
|
||||
.catch(requtil.ValidationError, function(err) {
|
||||
sendDone(false, err.reportCode || 'fail_validation')
|
||||
res.status(400)
|
||||
.json({
|
||||
success: false
|
||||
, error: 'ValidationError'
|
||||
, validationErrors: err.errors
|
||||
})
|
||||
})
|
||||
.catch(function(err) {
|
||||
log.error('Failed to save resource: ', err.stack)
|
||||
res.json(500, {
|
||||
success: false
|
||||
})
|
||||
log.error('Unexpected error', err.stack)
|
||||
sendDone(false, err.reportCode || 'fail')
|
||||
res.status(500)
|
||||
.json({
|
||||
success: false
|
||||
, error: 'ServerError'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user