You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.0 KiB
CoffeeScript

Promise = require "bluebird"
router = require("express-promise-router")()
errors = require "errors"
busboy = require "connect-busboy"
path = require "path"
fs = require "fs"
rfr = require "rfr"
config = rfr "config.json"
randomString = rfr "lib/random-string"
streamContains = rfr "lib/stream-contains"
tapError = rfr "lib/tap-error"
disableInMaintenanceMode = rfr "lib/disable-in-maintenance-mode"
router.post "/", disableInMaintenanceMode, busboy(limits: {fileSize: (config.upload_size_limit ? (150 * 1024 * 1024))}), (req, res) ->
Promise.try ->
Promise.all [
randomString 16
randomString 16
]
.spread (slugID, fileID) ->
storagePath = path.join config.storage_path, fileID
Promise.try ->
handleUpload req, res, storagePath: storagePath, fieldName: "file"
.then ->
headStream = fs.createReadStream storagePath, end: 1023
streamContains headStream, "%PDF"
.then (isPDF) ->
if isPDF
Promise.resolve()
else
Promise.reject new errors.InvalidFiletype "The file you uploaded is not a valid PDF file."
.then ->
objData =
SlugId: slugID
Public: (req.body.visibility == "public")
Views: 0
OriginalFilename: req.files.file.filename
Filename: fileID
Mirrored: 0
CDN: 0
Thumbnailed: 0
Uploaded: new Date()
DeleteKey: ""
req.model("Document").forge objData
.save()
.then (model) ->
if config.storage.ia and model.get("Public") == true
req.taskRunner.do "mirror", id: slugID
req.taskRunner.do "thumbnail", id: slugID
res.json {redirect: "/d/#{slugID}"}
.catch tapError (err) ->
# This is like a .tap, but for errors - it removes the file that was just uploaded.
fs.unlink storagePath, (err) ->
if err
req.reportError err
# TODO (CDN) SPEC: Then: (tasks abstracted to task file)
# * Create task: Tahoe-LAFS upload, update DB entry
# * Check if all tasks completed; if yes, remove file (but only if config says local storage is disabled).
handleUpload = (req, res, options) ->
if not req.busboy?
return Promise.resolve()
else
return new Promise (resolve, reject) ->
processFields req, res, options
processFiles req, res, options
req.busboy.on "finish", ->
resolve()
req.pipe req.busboy
processFields = (req, res, options) ->
req.body ?= {}
req.busboy.on "field", (name, value, keyTruncated, valueTruncated) ->
req.body[name] = value
processFiles = (req, res, options) ->
req.busboy.on "file", (name, file, filename, encoding, mimetype) ->
# TODO: Is the encoding taken care of automatically...?
if name != options.fieldName
# This is not the correct form field. Ignore it.
return
file
.on "limit", ->
# The maximum file size was exceeded.
file.unpipe()
reject new errors.UploadTooLarge "The file you attempted to upload is too large."
.pipe fs.createWriteStream(options.storagePath)
req.files ?= {}
req.files[name] =
filename: filename
encoding: encoding
mimetype: mimetype
storagePath: options.storagePath
module.exports = router