Skip to main content

文件上传下载示例

实现文件的上传下载

上传

server.js

import express from 'express';
import multer from 'multer';
import fs from 'fs';
import path from 'path';

// 创建 Express 应用实例
const app = express();
const PORT = 3000; // 服务器端口号

// ------------------------------
// 确保 uploads 文件夹存在,如果不存在则创建
// ------------------------------
const uploadDir = path.join(process.cwd(), 'uploads'); // 计算 uploads 文件夹的绝对路径
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir); // 创建 uploads 文件夹
}

// ------------------------------
// 配置 multer 存储策略
// ------------------------------
const storage = multer.diskStorage({
// 文件存储目的地
destination: (req, file, cb) => {
cb(null, uploadDir); // 上传的文件存放到 uploads 文件夹
},
// 文件名配置
filename: (req, file, cb) => {
cb(null, file.originalname); // 保留上传文件的原始文件名
}
});

// 初始化 multer 实例,使用上面定义的 storage 配置
const upload = multer({ storage });

// ------------------------------
// 文件上传接口
// ------------------------------
app.post('/upload', upload.single('file'), (req, res) => {
// 检查是否有文件上传
if (!req.file) {
return res.status(400).send('No file uploaded.'); // 如果没有文件,返回 400 错误
}
// 上传成功
res.send('File uploaded successfully!');
});

// ------------------------------
// 启动服务器
// ------------------------------
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

下载

server.js

import express from 'express';
import path from 'path';
import fs from 'fs';

const app = express();
const PORT = 3000;

// 文件存放目录
const downloadDir = path.join(process.cwd(), 'download');

// 通用下载接口
app.get('/download', (req, res) => {
const { filename } = req.query;

if (!filename) {
return res.status(400).send('Filename is required');
}

// 构造安全的文件路径,防止路径穿越
const filePath = path.join(downloadDir, path.basename(filename));

// 检查文件是否存在
if (!fs.existsSync(filePath)) {
return res.status(404).send('File not found');
}

// 下载文件
res.download(filePath, filename, (err) => {
if (err) {
console.error(err);
res.status(500).send('File download failed');
}
});
});

app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

// 确保当前目录有download目录,里面有1.png文件
// 文件下载链接 http://localhost:3000/download?filename=1.png

上传和下载

server.js

// -------------------- 引入依赖 --------------------

// Express 用于创建 Web 服务器
import express from 'express';

// Multer 用于处理文件上传
import multer from 'multer';

// path 用于处理文件和目录路径
import path from 'path';

// fs 文件系统模块,用于操作文件和目录
import fs from 'fs';

// fileURLToPath 用于把 ES Module 的 import.meta.url 转为文件路径
import { fileURLToPath } from 'url';

// -------------------- 获取当前文件路径 --------------------

// __filename 表示当前文件的完整路径,例如 C:\project\server.js
const __filename = fileURLToPath(import.meta.url);

// __dirname 表示当前文件所在的目录,例如 C:\project
const __dirname = path.dirname(__filename);

// -------------------- 创建 Express 应用 --------------------
const app = express();
const PORT = 3000; // 服务器端口

// -------------------- 上传和下载目录 --------------------

// 定义上传和下载文件存放的目录
const uploadDir = path.join(__dirname, 'uploads');

// 如果 uploads 文件夹不存在,就创建它
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}

// -------------------- 配置 Multer --------------------

// 配置文件存储方式
const storage = multer.diskStorage({
// 设置上传文件保存目录
destination: (req, file, cb) => {
cb(null, uploadDir);
},
// 设置上传文件的文件名
filename: (req, file, cb) => {
// 保留原始文件名,不修改
cb(null, file.originalname);
}
});

// 创建 multer 实例
const upload = multer({ storage });

// -------------------- 上传接口 --------------------

// POST /upload
// 使用 upload.single('file') 表示接收一个单文件上传,字段名为 'file'
app.post('/upload', upload.single('file'), (req, res) => {
// 如果没有文件上传,返回 400 错误
if (!req.file) return res.status(400).send('No file uploaded.');

// 上传成功,返回 JSON 数据
res.json({
message: 'File uploaded successfully', // 提示信息
filename: req.file.filename, // 保存到服务器的文件名
originalname: req.file.originalname // 原始文件名
});
});

// -------------------- 下载接口 --------------------

// GET /download?filename=xxx
app.get('/download', (req, res) => {
const { filename } = req.query; // 从 URL 查询参数获取文件名

// 如果没有提供文件名,返回 400 错误
if (!filename) return res.status(400).send('Filename is required.');

// 拼接文件完整路径
const filePath = path.join(uploadDir, filename);

// 判断文件是否存在
if (fs.existsSync(filePath)) {
// 文件存在,触发下载
res.download(filePath);
} else {
// 文件不存在,返回 404 错误
res.status(404).send('File not found.');
}
});

// -------------------- 文件列表接口 --------------------

// GET /files
// 返回 uploads 目录下的所有文件名
app.get('/files', (req, res) => {
const files = fs.readdirSync(uploadDir); // 读取目录
res.json(files); // 返回 JSON 数组
});

// -------------------- 启动服务器 --------------------
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});

接口测试

上传

curl --location --request POST 'http://localhost:3000/upload' \
--form 'file=@"C:\\Users\\kk\\Desktop\\图片\\z1.png"'

下载

curl --location --request GET 'http://localhost:3000/download?filename=z1.png'