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
109 lines
3.0 KiB
CoffeeScript
9 years ago
|
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
|