在 Node 中的无畏探险:全面掌握文件上传与下载
2023-09-13 06:59:52
一、Node的世界:初探文件上传
在Node的世界里,我们可以通过多种方式实现文件上传。其中一种便是Express框架与Multer的强强联手。Express提供轻量且灵活的框架,而Multer则专门负责文件上传,且它支持文件存储、类型检查等多种功能。
1. 拥抱Express:搭建坚实基石
Express是一个轻量级框架,可以轻松创建一个Node服务器。它提供灵活的路由系统,支持HTTP请求处理,帮助我们构建RESTful API。
// 引入Express
const express = require('express');
// 创建Express实例
const app = express();
// 创建路由
app.post('/upload', upload.single('file'), (req, res) => {
// 文件上传成功
res.json({ success: true, file: req.file });
});
2. 携手Multer:文件上传的得力助手
Multer是一个用于Node的中间件,专门处理文件上传。它提供各种配置选项,使我们能够轻松处理文件上传请求,以及对上传文件进行存储和解析。
// 引入Multer
const multer = require('multer');
// 配置Multer选项
const storage = multer.diskStorage({
destination: 'uploads/',
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname);
},
});
// 创建Multer实例
const upload = multer({ storage });
二、深入解析:Node文件下载之道
如同文件上传一样,Node也为文件下载提供了多种途径。我们依旧可以选择Express框架,结合Stream或Buffer的方式,轻松实现文件下载。
1. Express再出马:构建下载通道
依然是熟悉的Express框架,我们可以使用它来创建文件下载路由,并在路由处理函数中,通过流式传输或缓冲区的方式,将文件数据发送给客户端。
// 引入Express
const express = require('express');
// 创建Express实例
const app = express();
// 创建下载路由
app.get('/download/:file', (req, res) => {
const file = path.join(__dirname, 'uploads', req.params.file);
res.sendFile(file);
});
2. Stream:源源不断的传输之道
Stream流式传输是一种高效且实用的数据传输方式,它可以一边读取文件一边将其发送给客户端,无需将整个文件加载到内存中。
// 引入文件系统模块
const fs = require('fs');
// 创建文件流
const fileStream = fs.createReadStream(file);
// 将文件流发送给客户端
res.writeHead(200, { 'Content-Type': 'application/octet-stream' });
fileStream.pipe(res);
3. Buffer:内存中的文件持有者
Buffer是一种缓冲区,它可以在内存中存储二进制数据。我们可以先将文件读入缓冲区,然后再将缓冲区发送给客户端。
// 引入文件系统模块
const fs = require('fs');
// 读取文件到缓冲区
const fileBuffer = fs.readFileSync(file);
// 将缓冲区发送给客户端
res.writeHead(200, { 'Content-Type': 'application/octet-stream' });
res.end(fileBuffer);
三、扬帆远航:Node文件传输的无限可能
Node在文件上传和下载领域大放异彩,我们还可以根据实际需求,进一步拓展应用场景。
1. 多文件上传与下载:一次处理,轻松自如
我们可以利用Express和Multer的组合,实现多文件上传的功能。在客户端使用HTML5的<input type="file" multiple>
属性,就可以轻松选择多个文件进行上传。
对于文件下载,我们可以使用流式传输或缓冲区的方式,同时处理多个文件。
// 处理多文件上传
app.post('/upload-multiple', upload.array('files'), (req, res) => {
// 多个文件上传成功
res.json({ success: true, files: req.files });
});
// 处理多文件下载
app.get('/download-multiple', (req, res) => {
const files = req.query.files.split(',');
res.writeHead(200, { 'Content-Type': 'application/zip' });
const zip = archiver('zip');
zip.pipe(res);
files.forEach((file) => {
zip.append(fs.createReadStream(file), { name: file });
});
zip.finalize();
});
2. 断点续传:无惧网络波动
当网络连接不稳定时,断点续传可以确保文件传输不会中断。我们可以使用HTTP的Range头字段来实现断点续传。
// 断点续传
app.get('/download-resume', (req, res) => {
const file = path.join(__dirname, 'uploads', req.params.file);
const start = parseInt(req.headers['range'].split('=')[1].split('-')[0]);
const end = parseInt(req.headers['range'].split('=')[1].split('-')[1]);
const fileLength = fs.statSync(file).size;
if (start >= fileLength) {
res.status(416).end();
return;
}
if (end >= fileLength) {
end = fileLength - 1;
}
res.writeHead(206, {
'Content-Type': 'application/octet-stream',
'Content-Length': end - start + 1,
'Content-Range': `bytes ${start}-${end}/${fileLength}`,
});
const fileStream = fs.createReadStream(file, { start, end });
fileStream.pipe(res);
});
3. 文件预览:一睹为快
在某些场景下,我们可能需要在下载文件之前预览文件内容。我们可以利用Express和各种文件预览库,轻松实现文件预览功能。
// 文件预览
app.get('/preview/:file', (req, res) => {
const file = path.join(__dirname, 'uploads', req.params.file);
const mimeType = mime.getType(file);
if (mimeType.startsWith('image/')) {
res.writeHead(200, { 'Content-Type': mimeType });
fs.createReadStream(file).pipe(res);
} else if (mimeType.startsWith('video/')) {
res.writeHead(200, { 'Content-Type': mimeType });
const ffmpeg = require('fluent-ffmpeg');
ffmpeg(file)
.outputFormat('mp4')
.videoCodec('libx264')
.audioCodec('aac')
.outputOptions('-movflags faststart')
.size('320x240')
.on('error', (err) => {
console.error(err);
res.status(500).end();
})
.on('progress', (progress) => {
console.log(`Preview progress: ${progress.percent}%`);
})
.on('end', () => {
console.log('Preview generated');
res.end();
})
.pipe(res, { end: true });
} else {
res.status(400).end();
}
});
结语
Node凭借其强大且灵活的特性,在文件上传和下载领域,为我们提供了丰富的选择和强大的功能。无论是简单的文件传输,还是复杂的多文件处理和文件预览,Node都能轻松应对。让我们一起探索Node的奥秘,在文件管理的广阔天地中乘风破浪。