-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
133 lines (121 loc) · 4.32 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import dotenv from 'dotenv';
dotenv.config({ path: '.mytest.env' });
import PrismaClient from '@prisma/client';
import multer from 'multer';
import { createHmac } from "crypto";
import express from "express";
import morgan from 'morgan';
import process from 'process';
import fs from 'fs';
import path from 'path';
import mime from 'mime-types';
export const db = new PrismaClient.PrismaClient({ log: ['query'] });
export async function connect() {
try {
console.log(new Date(), `connecting to db ${process.env.DB_PATH}`);
await db.$connect();
console.log(new Date(), 'connected to db');
} catch (e) {
console.log(new Date(), 'connect to db failed', e);
throw e;
}
}
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
function randomPlace() {
return [1, 2, 3, 4, 5].map(() => chars[Math.floor(Math.random() * chars.length)]).join('');
}
const withCatch = fn => {
return function (req, res, next) {
fn(req, res, next).catch(e => {
(res.closes || []).forEach(r => r.close());
console.log('ERROR', new Date());
console.log(e.toString());
console.log(e?.stack);
next(e);
});
}
};
export const app = express();
app.use(morgan('dev'));
app.use(express.static('static', { index: 'main.html' }));
app.use(express.json({ limit: '32mb' }));
const port = parseInt(process.env.HTTP_PORT) || 3080;
app.get('/healthz', (r_, res) => {
res.status(200).end();
});
const upload = multer({ dest: '/tmp/lhd-multer-tmp-files/' }).single('form-input-name');
app.post('/data/', withCatch(async (req, res) => {
{
let r, e;
const p = new Promise((r_, e_) => { r = r_; e = e_; });
upload(req, res, err => {
if (err){
console.log(new Date(), `upload error ${err}`);
e(err)
}
else
r()
});
await p;
console.log(new Date(), `req.files:${req.file.path}`);
}
let tinyUrl, item;
tinyUrl = req.query.tinyUrl || randomPlace();
while (true) {
try {
item = await db.file.create({
data: {
fileName: req.query.fileName || 'file.bin',
ready: false,
mime: req.query.mime || mime.contentType(req.query.fileName || 'file.bin') || 'application/octet-stream',
tinyUrl,
}
});
break;
} catch (err) {
if (err.code == 'P2002') {
const old = tinyUrl;
tinyUrl = randomPlace();
console.log(new Date(), `url hash ${old} conflict, re-generate: ${tinyUrl}`);
continue;
}
throw err;
}
}
fs.mkdirSync(path.join(process.env.FILE_PATH, `${tinyUrl[0]}/${tinyUrl[1]}`), { recursive: true });
fs.renameSync(req.file.path, path.join(process.env.FILE_PATH, `${tinyUrl[0]}/${tinyUrl[1]}/${tinyUrl}`));
// let onFinsh, onError;
// let p = new Promise((r, e) => { onFinsh = r; onError = e; });
// const dest = fs.createWriteStream(path.join(process.env.FILE_PATH, `${tinyUrl[0]}/${tinyUrl[1]}/${item.tinyUrl}`));
// res.closes = [dest];
// req.pipe(dest);
// req.on('end', () => onFinsh());
// req.on('error', err => onError(err));
//await p;
await db.file.update({
where: { tinyUrl },
data: { ready: true }
});
item.ready = true;
res.json(item).end();
}));
app.get('/data/:tinyUrl', withCatch(async (req, res) => {
const item = await db.file.findUnique({
where: { tinyUrl: req.params.tinyUrl },
});
res.set('content-type', item.mime);
res.set('content-disposition', `inline; filename="${item.fileName}"`);
let onFinsh, onError;
let p = new Promise((r, e) => { onFinsh = r; onError = e; });
const src = fs.createReadStream(path.join(process.env.FILE_PATH, `${item.tinyUrl[0]}/${item.tinyUrl[1]}/${item.tinyUrl}`));
res.closes = [src];
src.pipe(res);
src.on('end', () => onFinsh());
src.on('error', err => onError(err));
await p;
//res.end() should triggered by pipe's 'end' event
}));
await connect();
if (process.argv[1].endsWith('main.js')) {
app.listen(port, () => console.log(new Date(), `server at port ${port}`));
}