思路 (文件上传限制可按需求修改)
- 使用 express 搭建服务器,使用 multer 用于解析 formData 文件数据,并放置在根目录中 uploads 文件夹中;
- 使用 express.static() 创建 静态服务器,并将请求路径设置为 /file,该静态服务器指向为放置上传文件的 uploads 文件夹内;
- 使用 path 模块遍历 uploads 文件夹中所有文件,并因此获得文件夹中的所有文件的相对路径
- 使用 http 模块尝试获取当前公网 IP,用于拼接数组中完整的文件下载地址。最终使用 对应路由 返回给用户
实现接口
请求路径 | 请求类型 | 参数 | 业务 |
---|---|---|---|
/addFile | post | file | 使用 formData 上传文件 |
/delFile | get | fileName | 以文件完整扩展名删除指定文件 |
/fileAll | get | 无 | 获取静态服务器中所有文件 |
返回格式
{
"status": 200,
"file": [
{
"file": "周杰伦-东风破.mp3",
"fileName": "周杰伦-东风破",
"fileSrc": "http://对应服务器部署的公网IP地址:82/file/周杰伦-东风破.mp3"
},
{
"file": "周杰伦-倒影.mp3",
"fileName": "周杰伦-倒影",
"fileSrc": "http://对应服务器部署的公网IP地址:82/file/周杰伦-倒影.mp3"
},
{
"file": "周杰伦-兰亭序.mp3",
"fileName": "周杰伦-兰亭序",
"fileSrc": "http://对应服务器部署的公网IP地址:82/file/周杰伦-兰亭序.mp3"
}
]
}
操作
安装第三方库
npm i express multer cors
完整代码
具体需要限制上传的文件类型可按需更改
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
const http = require('http');
// 配置 https
// let privateKey = fs.readFileSync('/path/to/private.pem', 'utf8');
// let certificate = fs.readFileSync('/path/to/file.crt', 'utf8');
// let credentials = {key: privateKey, cert: certificate};
const port = 82;
// 获取 公网 IP地址
async function getPublicIpAddress() {
return new Promise((resolve, reject) => {
// 向一个公网 IP 地址发送 HTTP 请求,获取本机 IP 地址
http.get('http://icanhazip.com/', res => {
res.setEncoding('utf8');
let ipAddress = '';
res.on('data', chunk => {
ipAddress += chunk;
});
res.on('end', () => {
// 去掉 IP 地址字符串中的空格和换行符
ipAddress = ipAddress.trim();
resolve(ipAddress);
});
}).on('error', err => {
console.error(`获取公网 IP 地址失败: ${err.message}`);
reject(err);
});
});
}
// 遍历文件夹内容
async function readDirFiles(dirPath, files = [], prefix = '/file') {
// 读取目标文件夹中的所有文件和子文件夹
fs.readdirSync(dirPath).forEach(file => {
// 构造文件的相对路径
const filePath = path.join(prefix, file);
// 判断文件类型,如果是文件夹,则递归遍历子文件夹,否则将文件路径保存到数组中
if (fs.statSync(path.join(dirPath, file)).isDirectory()) {
readDirFiles(path.join(dirPath, file), files, `${filePath}/`);
} else {
files.push(filePath);
}
});
return files.map(e => e.replace(/\\/g, '/'));
}
// 删除指定文件夹内容
async function deleteFile(filePath, prefix = './uploads') {
const fileName = path.join(prefix, filePath);
console.log(fileName);
// 使用 fs.unlink() 方法删除指定文件名的文件
try {
await fs.promises.unlink(fileName);
return true;
} catch (err) {
console.error(err);
return false;
}
}
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 使用静态服务器 路径为 file
app.use('/file', express.static('./uploads'));
// 配置 multer 中间件
const storage = multer.diskStorage({
// 文件放置位置
destination: 'uploads/',
// 指定文件上传后的保存路径和文件名
filename: (req, file, cb) => {
console.log(file.mimetype);
cb(null, decodeURI(file.originalname));
}
});
const upload = multer({ storage });
// 处理 POST /addSong 请求
app.post('/addFile', upload.single('file'), (req, res) => {
// req.file 是上传的文件信息,可以通过它来获取文件名、大小等信息
console.log(req.file);
// 判断是否有上传的音频文件
if (!req.file) {
return res.status(400).json({
success: false,
message: '请上传文件'
});
}
// 返回一个 JSON 响应
res.json({
success: true,
message: '文件上传成功'
});
});
app.get('/fileAll', async function (req, res) {
const ip = await getPublicIpAddress();
const fileList = await readDirFiles(path.join(__dirname, './uploads'));
const file = fileList.map(function (e) {
let file = path.basename(e);
let fileName = path.basename(e, path.extname(e));
let fileSrc = 'http://' + ip + ':' + port + e;
return {
file,
fileName,
fileSrc
}
});
res.send({
status: 200,
file: file
})
});
app.get('/delFile', async function (req, res) {
if (req.query.fileName) {
const name = req.query.flieName;
console.log(name);
const result = await deleteFile(name);
if (!result) return res.send({ status: 400, message: '删除失败' });
res.send({ status: 200, message: '删除成功' });
} else {
res.send({ status: 400, message: '请选择需要删除的内容' })
}
})
app.listen(port, async () => {
const ip = await getPublicIpAddress();
console.log('服务器运行在 http://' + ip + ':' + port + ' 上.');
})