214 lines
6.3 KiB
JavaScript
214 lines
6.3 KiB
JavaScript
import express from 'express'
|
|
import cors from 'cors'
|
|
import Database from 'better-sqlite3';
|
|
import fs from "fs"
|
|
|
|
|
|
|
|
const HOST = '0.0.0.0'
|
|
const PORT = '17058'
|
|
const fileDir = "./temp";
|
|
const dbPath = './miaoShare.db'
|
|
// 上传文件最大大小:200MB
|
|
const uploadMaxSize=200*1024*1024
|
|
// 一天的毫秒数
|
|
const millisecondsOfTheDay = parseInt(24*3600*1000)
|
|
// 文件3天过期
|
|
const LifeOfFile=millisecondsOfTheDay*3
|
|
// const LifeOfFile=0
|
|
|
|
// 数据库相关
|
|
const db = new Database(dbPath, { verbose: null });
|
|
db.prepare(`CREATE TABLE IF NOT EXISTS id2fileName (
|
|
id CHAR(8) PRIMARY KEY NOT NULL UNIQUE,
|
|
fileName TEXT NOT NULL,
|
|
timestamp INT NOT NULL,
|
|
freeze tinyint(1) NOT NULL,
|
|
downloadCredit INT NOT NULL
|
|
);`).run()
|
|
const stmt_getFileName = db.prepare(`SELECT fileName FROM id2fileName WHERE id = ?`)
|
|
const stmt_getTimestamp = db.prepare(`SELECT timestamp FROM id2fileName WHERE id = ?`)
|
|
const stmt_getFreeze = db.prepare(`SELECT freeze FROM id2fileName WHERE id = ?`)
|
|
const stmt_getDownloadCredit = db.prepare(`SELECT downloadCredit FROM id2fileName WHERE id = ?`)
|
|
const stmt_getFreezenIDs = db.prepare(`SELECT id FROM id2fileName WHERE freeze = 1`)
|
|
const stmt_insertId2FileName = db.prepare(`INSERT INTO id2fileName (id, fileName, timestamp, freeze, downloadCredit) VALUES (?, ?, ?, ?, ?)`)
|
|
const stmt_deleteExpireData = db.prepare(`DELETE FROM id2fileName WHERE freeze=1`)
|
|
const stmt_freezeExpireData = db.prepare(`UPDATE id2fileName SET freeze=1 WHERE timestamp < ? OR downloadCredit < 1`)
|
|
const stmt_updateDownloadCredit = db.prepare(`UPDATE id2fileName SET downloadCredit=downloadCredit-1 WHERE id = ?`)
|
|
|
|
const db_insert = (id,fileName,downloadCredit)=>{
|
|
stmt_insertId2FileName.run(id,fileName,parseInt(Date.now()),0,downloadCredit)
|
|
}
|
|
const db_getFileName = (id)=>{
|
|
try{
|
|
if(stmt_getFreeze.get(id)['freeze'] == 1)return null
|
|
return stmt_getFileName.get(id)['fileName']
|
|
}catch(e){
|
|
return null
|
|
}
|
|
}
|
|
// 检查是否可下载
|
|
const db_downloadable = (id)=>{
|
|
try{
|
|
// 懒
|
|
if(stmt_getDownloadCredit.get(id)['downloadCredit'] < 1)return false
|
|
if(stmt_getFreeze.get(id)['freeze'] == 1)return false
|
|
return true
|
|
}catch(e){
|
|
return false
|
|
}
|
|
}
|
|
const db_updateDownloadCredit = (id)=>{
|
|
try{
|
|
stmt_updateDownloadCredit.run(id)
|
|
return true
|
|
}catch(e){
|
|
return false
|
|
}
|
|
}
|
|
|
|
const db_getTimestamp = (id)=>{
|
|
return stmt_getTimestamp.get(id)['timestamp']
|
|
}
|
|
|
|
// 更新存储的文件,删除已经被冻结的文件以及相关记录,然后冻结过期文件
|
|
const updateFiles = ()=>{
|
|
try{
|
|
let rows = stmt_getFreezenIDs.all()
|
|
stmt_deleteExpireData.run()
|
|
for(let row of rows){
|
|
let fileName = row['id']
|
|
let path = fileDir + '/' + fileName
|
|
try{
|
|
fs.unlink(path,(e)=>{if(e)throw e})
|
|
}catch(e){
|
|
console.log(e)
|
|
continue
|
|
}
|
|
}
|
|
stmt_freezeExpireData.run(parseInt(Date.now()) - LifeOfFile)
|
|
}catch(e){
|
|
console.log(e)
|
|
return
|
|
}
|
|
}
|
|
updateFiles()
|
|
// 3小时更新一次
|
|
setInterval(updateFiles,1000*3600*3)
|
|
|
|
|
|
var app = express();
|
|
app.use(cors());
|
|
var tempMap = {}
|
|
|
|
if (!fs.existsSync(fileDir)) {
|
|
fs.mkdirSync(fileDir);
|
|
}
|
|
|
|
function generateId(){
|
|
var returnStr = "",
|
|
range = 8,
|
|
charStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
|
|
for(var i=0; i<range; i++){
|
|
var index = Math.round(Math.random() * 35);
|
|
returnStr += charStr.substring(index,index+1);
|
|
}
|
|
return returnStr;
|
|
}
|
|
|
|
// 上传文件接口
|
|
function uploadFile(req, res, fileName, downloadCredit){
|
|
let id = generateId();
|
|
const fileStream = fs.createWriteStream(fileDir + '/' + id);
|
|
db_insert(id,fileName,downloadCredit)
|
|
// tempMap[id] = fileName;
|
|
// console.log(tempMap);
|
|
req.pipe(fileStream);
|
|
res.on('data',(c)=>{console.log(c)})
|
|
req.on("end", function () {
|
|
fileStream.end();
|
|
res.statusCode = 200;
|
|
res.end(id);
|
|
});
|
|
req.on("error", err => {
|
|
fileStream.end();
|
|
res.statusCode = 500;
|
|
res.end("File save failed: " + err.message);
|
|
});
|
|
}
|
|
|
|
function downloadFile(req, res, fileId){
|
|
try {
|
|
if(db_downloadable(fileId) == false){
|
|
res.writeHead(404);
|
|
res.end(null);
|
|
return
|
|
}
|
|
db_updateDownloadCredit(fileId)
|
|
var fileName = db_getFileName(fileId)
|
|
if(fileName == null){
|
|
res.writeHead(404);
|
|
res.end(null);
|
|
return
|
|
}
|
|
let data = fs.readFileSync(fileDir + '/' + fileId);
|
|
res.writeHead(200, {
|
|
"Content-Type": "application/octet-stream ",
|
|
"File-Name": fileName,
|
|
'Content-Length':data.length,
|
|
});
|
|
res.end(data);
|
|
} catch (err) {
|
|
console.log(err);
|
|
res.writeHead(404);
|
|
res.end(null);
|
|
}
|
|
}
|
|
|
|
// 设置一些通用的中间件
|
|
// app.use(bodyParser.json());
|
|
// app.use(bodyParser.urlencoded({extended: true}));
|
|
|
|
// app.all()
|
|
app.post('/file/upload', function(req, res){
|
|
res.header("Access-Control-Allow-Origin", "*");
|
|
res.header("Access-Control-Allow-Headers", "*");
|
|
res.header("Access-Control-Allow-Methods", "POST");
|
|
res.header("Access-Control-Expose-Headers", "File-Name");
|
|
var fileSize = parseInt(req.get('Content-Length'))
|
|
var fileName = req.query.fileName;
|
|
var downloadCredit = parseInt(req.query.downloadCredit);
|
|
if(downloadCredit == -1)downloadCredit = 2147483647
|
|
if(!fileName){
|
|
res.statusCode = 500;
|
|
res.end("FileName Not Found");
|
|
}else if(fileSize > uploadMaxSize){
|
|
res.statusCode = 500;
|
|
res.end("Maximum size limit exceeded");
|
|
}
|
|
else{
|
|
uploadFile(req, res, fileName, downloadCredit);
|
|
}
|
|
});
|
|
|
|
app.get('/file/download', function(req, res){
|
|
res.header("Access-Control-Allow-Origin", "*");
|
|
res.header("Access-Control-Allow-Headers", "*");
|
|
res.header("Access-Control-Allow-Methods", "GET");
|
|
res.header("Access-Control-Expose-Headers", "File-Name");
|
|
var fileId = req.query.fileName;
|
|
if(!fileId){
|
|
res.statusCode = 500;
|
|
res.end("FileName Not Found");
|
|
}else{
|
|
downloadFile(req, res, fileId);
|
|
}
|
|
});
|
|
|
|
// 启动服务器
|
|
app.listen(PORT, HOST, function(){
|
|
// console.log('Example app listening on port ' + PORT + '.');
|
|
});
|
|
|