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{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 + '.'); });