This repository has been archived by the owner on Mar 19, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
107 lines (85 loc) · 2.64 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
const path = require("path")
const util = require("util")
const express = require("express")
const fileUpload = require("express-fileupload")
const mkdirp = util.promisify(require("mkdirp"))
const nanoid = require("nanoid")
const debug = require("debug")("image-uploader")
const VOLUME = path.resolve(process.env.VOLUME || "./files")
const ID_LENGTH = 30
const LISTEN_PORT = process.env.LISTEN_PORT
? parseInt(process.env.LISTEN_PORT, 10)
: 4000
const NO_UPLOADS = () => ({ error: "no_uploads" })
const UPLOAD_OK = ({ path, name }) => ({ ok: true, path, name })
const UPLOAD_FAILED = ({ error, name }) => ({ ok: false, error, name })
const RESULT = ({ status, files }) => ({ status, files })
const app = express()
app.use(fileUpload())
app.post("/upload", handler)
const server = app.listen(LISTEN_PORT, () => {
console.log("Listening port", LISTEN_PORT)
})
process.on("SIGINT", () => {
console.log("Stopping server")
server.close()
})
async function handler(req, res) {
const fileNames = Object.keys(req.files)
debug("request to upload ", fileNames)
if (!req.files || fileNames.length === 0) {
return res.status(400).json(NO_UPLOADS())
}
const results = await Promise.all(
fileNames.map((name) => save(name, req.files[name])),
)
const allUploaded = results.every(({ ok }) => ok)
const allFailed = results.every(({ ok }) => !ok)
const status = allUploaded ? "ok" : allFailed ? "failed" : "partial"
res.status(200).json(RESULT({ status, files: results }))
}
async function save(name, file) {
const id = nanoid(ID_LENGTH)
debug("saving file ", file.name, id)
try {
const ext = getExtension(file.name)
const dir = await createDirectory()
debug("created dir", dir)
const path = `${dir}/${id}.${ext}`
await move(file, `${VOLUME}${path}`)
debug("saved file to", path)
console.log("uploader: ", path)
return UPLOAD_OK({ path, name })
} catch (error) {
debug("failed to move", error)
return UPLOAD_FAILED({ name, error: String(error) })
// return save(file)
}
}
async function createDirectory() {
const first = nanoid(4)
const second = nanoid(4)
const path = `/${first}/${second}`
try {
await mkdirp(`${VOLUME}${path}`)
return path
} catch (error) {
debug("failed to create directory", error)
return createDirectory()
}
}
function move(file, to) {
debug("moving file", file, to)
return new Promise((resolve, reject) => {
file.mv(to, (err) => {
if (err) {
debug("failed to move file", err)
return reject(err)
}
return resolve(file)
})
})
}
function getExtension(fileName) {
return fileName.split(".").pop() || "jpg"
}