用Nodejs写了个HTTP文件服务器,好蛋疼
用Nodejs写了个HTTP文件服务器,好蛋疼
现在express里有个文件名的bug, res.sendfile, res.download之类的都有, 不支持路径中有中文名称包括文件名 后端用mongodb存文件全路径,下载时只通过id传, 原来想直接传全文件路径比如C:\works\a.txt,后来发现不行,好象security限制住了,根本不会route到/download/:filename的处理,直接显示无法GET…
主要两个页面,一个Add file, 一个显示所有文件,点击任意一个即可下载
exports.down = function(req, res){
var MongoClient = require('mongodb').MongoClient;
var fs = require('fs');
var path = require('path');
var ObjectID = require('mongodb').ObjectID;
MongoClient.connect(“mongodb://localhost:27017/filelist”, function(err, db) {
if (!err) {
console.log(“We are connected.”);
}
var fileid = req.params.id;
var collection = db.collection('filelink');
collection.findOne({"_id": ObjectID(fileid)}, function(err, item) {
var filepath = item["file"];
var filebase = path.basename(filepath);
//console.log(filepath);
//console.log(filebase);
res.download(filepath,filebase);
});
});
};
标题是lz自嘲?
楼主不蛋疼,谁蛋疼! 一个简单的文件服务器都要搬出mongodb
大炮打蚊子
要保存状态啊,象HFS一样, 如果没有persistence, 下次开启时又没有了,上次share的列表, 你用文件去存一个列表也是一样。。。。 这个是可以共享任意磁盘上的文件的,不是那个public文件夹share, 设置一下就可以了
我也觉得,原来想用sqlite3, 结果那个傻X的sqlite npm package装不起来, 老是在node-gyp编译时出错 有空再试试
发一下写来自己用的非常简单的静态文件服务器,不需要express,mongodb,sqlite…
var PORT = 8090;
var MIME = {
'htm': 'text/html',
'html': 'text/html',
'css': 'text/css',
'gif': 'image/gif',
'ico': 'image/x-icon',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'png': 'image/png',
'rar': 'application/x-rar-compressed',
'txt': 'text/plain',
'json': 'text/plain',
'jar': 'application/java-archive'
};
var dir = process.argv[2];
var ROOT = dir ? dir : process.cwd();
var http = require(‘http’);
var url = require(‘url’);
var fs = require(‘fs’);
var path = require(‘path’);
http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname;
var realpath = pathname !== ‘/’ ? ROOT + pathname : __filename;
var extname = path.extname(realpath).slice(1);
var contentType = ‘text/plain’;
if (extname && MIME[extname]) {
contentType = MIME[extname];
}
fs.exists(realpath, function(exists) {
if (exists) {
fs.readFile(realpath, function(err, data) {
if (err) throw err;
response.writeHead(200, {'Content-Type': contentType});
response.write(data);
response.end();
});
} else {
response.writeHead(404, {'Content-Type': 'text/plain'});
response.write('Not Found');
response.end();
}
});
}).listen(PORT);
console.log('simple static file server runing at port: ’ + PORT + ‘.’);
__filename 不如改成index.html
针对你的问题,确实存在一些关于路径处理和文件下载的安全性问题。这里提供一种解决方案,使用 res.sendFile
方法来代替 res.download
,并且确保路径是安全的。
以下是修改后的代码示例:
const express = require('express');
const fs = require('fs');
const path = require('path');
const MongoClient = require('mongodb').MongoClient;
const app = express();
app.get('/download/:id', (req, res) => {
const fileId = req.params.id;
const dbUrl = "mongodb://localhost:27017/filelist";
MongoClient.connect(dbUrl, { useNewUrlParser: true, useUnifiedTopology: true }, (err, db) => {
if (err) {
return res.status(500).send({ error: 'Database connection failed' });
}
const dbo = db.db("filelist");
const collection = dbo.collection('filelink');
collection.findOne({ "_id": new ObjectID(fileId) }, (err, result) => {
if (err || !result) {
return res.status(404).send({ error: 'File not found' });
}
const filePath = decodeURIComponent(result.file);
const fileName = path.basename(filePath);
if (!fs.existsSync(filePath)) {
return res.status(404).send({ error: 'File does not exist' });
}
res.sendFile(filePath, { root: __dirname }, (err) => {
if (err) {
console.error(err);
res.status(err.status).end();
} else {
console.log(`Sent: ${filePath}`);
}
});
});
db.close();
});
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
关键点解释:
- 路径解码:
decodeURIComponent
用于解码可能包含特殊字符(如中文)的路径。 - 文件存在检查:在发送文件之前,先检查文件是否存在。
- 使用
res.sendFile
:该方法支持传递根目录参数,并且可以处理路径中的特殊字符。
这样处理后,可以避免由于路径编码问题导致的文件找不到或不能下载的情况。同时,也保证了安全性。