linux

Linux Node.js如何实现文件上传下载功能

小樊
49
2025-05-17 22:06:41
栏目: 编程语言

在Linux环境下使用Node.js实现文件的上传和下载功能,通常会借助一些流行的框架和中间件。以下是使用Express.js框架结合Multer(用于上传)和Express.static(用于下载)来实现这一功能的详细步骤。

1. 环境准备

安装Node.js和npm

首先,确保你的Linux系统上已经安装了Node.js和npm。你可以通过以下命令检查是否已安装:

node -v
npm -v

如果未安装,可以访问Node.js官网下载并安装适合你系统的版本。

创建项目目录

创建一个新的项目目录并进入:

mkdir file-upload-download
cd file-upload-download

初始化npm

初始化一个新的Node.js项目:

npm init -y

2. 安装必要的依赖

安装Express.js和Multer:

npm install express multer

3. 实现文件上传功能

创建一个名为app.js的文件,并添加以下代码:

const express = require('express');
const multer  = require('multer');
const path = require('path');

const app = express();

// 设置存储引擎
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads/') // 设置上传文件的存储目录
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname) // 重命名文件以避免冲突
  }
});

// 初始化上传
const upload = multer({
  storage: storage,
  limits: { fileSize: 10 * 1024 * 1024 }, // 限制文件大小为10MB
  fileFilter: function (req, file, cb) {
    checkFileType(file, cb);
  }
}).single('file'); // 'file' 是表单中文件字段的名称

// 检查文件类型
function checkFileType(file, cb) {
  // 允许的扩展名
  const filetypes = /jpeg|jpg|png|gif/;
  // 检查扩展名
  const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
  // 检查MIME类型
  const mimetype = filetypes.test(file.mimetype);

  if (mimetype && extname) {
    return cb(null, true);
  } else {
    cb('Error: Images Only!');
  }
}

// 上传路由
app.post('/upload', (req, res) => {
  upload(req, res, (err) => {
    if (err) {
      res.status(400).send({ message: err });
    } else {
      if (req.file == undefined) {
        res.status(400).send({ message: 'No file selected!' });
      } else {
        res.send({
          message: 'File uploaded!',
          file: `uploads/${req.file.filename}`
        });
      }
    }
  });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

创建上传目录

在项目根目录下创建一个uploads文件夹,用于存放上传的文件:

mkdir uploads

运行服务器

启动服务器:

node app.js

服务器将在http://localhost:3000运行。

4. 实现文件下载功能

修改app.js,添加下载路由:

// 下载路由
app.get('/download/:filename', (req, res) => {
  const { filename } = req.params;
  const filePath = path.join(__dirname, 'uploads', filename);

  // 检查文件是否存在
  fs.access(filePath, fs.constants.F_OK, (err) => {
    if (err) {
      return res.status(404).send({ message: 'File not found!' });
    }
    res.download(filePath, filename, (err) => {
      if (err) throw err;
    });
  });
});

确保引入fs模块:

const fs = require('fs');

完整代码如下:

const express = require('express');
const multer  = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();

// 设置存储引擎
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads/') // 设置上传文件的存储目录
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname) // 重命名文件以避免冲突
  }
});

// 初始化上传
const upload = multer({
  storage: storage,
  limits: { fileSize: 10 * 1024 * 1024 }, // 限制文件大小为10MB
  fileFilter: function (req, file, cb) {
    checkFileType(file, cb);
  }
}).single('file'); // 'file' 是表单中文件字段的名称

// 检查文件类型
function checkFileType(file, cb) {
  // 允许的扩展名
  const filetypes = /jpeg|jpg|png|gif/;
  // 检查扩展名
  const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
  // 检查MIME类型
  const mimetype = filetypes.test(file.mimetype);

  if (mimetype && extname) {
    return cb(null, true);
  } else {
    cb('Error: Images Only!');
  }
}

// 上传路由
app.post('/upload', (req, res) => {
  upload(req, res, (err) => {
    if (err) {
      res.status(400).send({ message: err });
    } else {
      if (req.file == undefined) {
        res.status(400).send({ message: 'No file selected!' });
      } else {
        res.send({
          message: 'File uploaded!',
          file: `uploads/${req.file.filename}`
        });
      }
    }
  });
});

// 下载路由
app.get('/download/:filename', (req, res) => {
  const { filename } = req.params;
  const filePath = path.join(__dirname, 'uploads', filename);

  // 检查文件是否存在
  fs.access(filePath, fs.constants.F_OK, (err) => {
    if (err) {
      return res.status(404).send({ message: 'File not found!' });
    }
    res.download(filePath, filename, (err) => {
      if (err) throw err;
    });
  });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

5. 测试文件上传和下载

使用Postman测试上传

  1. 打开Postman
  2. 创建一个新的POST请求,URL为http://localhost:3000/upload
  3. Body选项卡中,选择form-data
  4. 添加一个键为file,类型为File的字段,并选择要上传的文件。
  5. 点击Send发送请求。

如果上传成功,你将收到类似以下的响应:

{
  "message": "File uploaded!",
  "file": "uploads/1697052345678-image.jpg"
}

使用浏览器测试下载

  1. 访问http://localhost:3000/download/1697052345678-image.jpg(将文件名替换为你实际上传的文件名)。
  2. 浏览器将开始下载该文件。

6. 安全性考虑

在实际应用中,需要注意以下几点以确保文件上传和下载的安全性:

  1. 验证用户权限:确保只有授权用户才能上传和下载文件。
  2. 限制文件类型和大小:根据需求限制允许上传的文件类型和大小,防止服务器资源被滥用。
  3. 防止路径遍历攻击:在处理文件下载时,确保用户无法通过修改URL访问到不应该公开的文件。
  4. 存储安全:将上传的文件存储在非Web根目录下,避免直接通过浏览器访问。
  5. 使用HTTPS:在生产环境中,使用HTTPS加密传输数据,保护数据安全。

7. 完整代码示例

以下是完整的app.js代码,整合了上传和下载功能:

const express = require('express');
const multer  = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();

// 设置存储引擎
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads/') // 设置上传文件的存储目录
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname) // 重命名文件以避免冲突
  }
});

// 初始化上传
const upload = multer({
  storage: storage,
  limits: { fileSize: 10 * 1024 * 1024 }, // 限制文件大小为10MB
  fileFilter: function (req, file, cb) {
    checkFileType(file, cb);
  }
}).single('file'); // 'file' 是表单中文件字段的名称

// 检查文件类型
function checkFileType(file, cb) {
  // 允许的扩展名
  const filetypes = /jpeg|jpg|png|gif/;
  // 检查扩展名
  const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
  // 检查MIME类型
  const mimetype = filetypes.test(file.mimetype);

  if (mimetype && extname) {
    return cb(null, true);
  } else {
    cb('Error: Images Only!');
  }
}

// 上传路由
app.post('/upload', (req, res) => {
  upload(req, res, (err) => {
    if (err) {
      res.status(400).send({ message: err });
    } else {
      if (req.file == undefined) {
        res.status(400).send({ message: 'No file selected!' });
      } else {
        res.send({
          message: 'File uploaded!',
          file: `uploads/${req.file.filename}`
        });
      }
    }
  });
});

// 下载路由
app.get('/download/:filename', (req, res) => {
  const { filename } = req.params;
  const filePath = path.join(__dirname, 'uploads', filename);

  // 检查文件是否存在
  fs.access(filePath, fs.constants.F_OK, (err) => {
    if (err) {
      return res.status(404).send({ message: 'File not found!' });
    }
    res.download(filePath, filename, (err) => {
      if (err) throw err;
    });
  });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

8. 总结

通过以上步骤,你可以在Linux环境下使用Node.js和Express.js实现文件的上传和下载功能。根据实际需求,你可以进一步扩展功能,例如添加用户认证、文件列表展示、删除文件等。同时,务必注意安全性,确保应用在生产环境中的稳定和安全运行。

0
看了该问题的人还看了