在现代 Web 开发中,文件上传和下载已经成为了必要的功能之一。Node.js 作为一种轻量、高效的服务器端技术,为我们提供了简单易用的文件读写 API 来进行文件上传与下载操作。本文将详细介绍 Node.js 中如何进行文件上传与下载操作,为希望学习这方面知识的开发者提供详细指导。
文件上传
上传单个文件
要上传单个文件,我们需要使用 formidable
模块来解析上传请求,然后使用 Node.js 内置的 fs
模块来将文件保存到文件系统中。示例代码如下:
// javascriptcn.com 代码示例 const http = require('http'); const formidable = require('formidable'); const fs = require('fs'); http.createServer((req, res) => { if (req.url == '/upload' && req.method.toLowerCase() == 'post') { const form = formidable({ multiples: false }); form.parse(req, (err, fields, file) => { if (err) { console.error(err.message); return; } const oldPath = file.upload.path; const newPath = 'uploads/' + file.upload.name; fs.rename(oldPath, newPath, err => { if (err) { console.error(err.message); return; } res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('File uploaded and moved!'); res.end(); }); }); return; } res.writeHead(200, {'Content-Type': 'text/html'}); res.end(` <form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="upload" /> <input type="submit" value="Upload" /> </form> `); }).listen(8080);
这段代码演示了如何使用 formidable
模块解析上传请求,读取文件并存储在服务器的 /uploads
目录下。 服务器返回 "File uploaded and moved!" 来指示文件上传成功。
上传多个文件
要上传多个文件,我们只需要将 formidable
模块中的 multiples
选项设置为 true
,这样就可以处理多个文件上传请求。示例代码如下:
// javascriptcn.com 代码示例 const http = require('http'); const formidable = require('formidable'); const fs = require('fs'); http.createServer((req, res) => { if (req.url == '/upload' && req.method.toLowerCase() == 'post') { const form = formidable({ multiples: true }); form.parse(req, (err, fields, files) => { if (err) { console.error(err.message); return; } const uploadedFiles = Object.values(files); const newPaths = uploadedFiles.map(file => 'uploads/' + file.name); Promise.all(uploadedFiles.map(file => { return new Promise((resolve, reject) => { const oldPath = file.path; const newPath = 'uploads/' + file.name; fs.rename(oldPath, newPath, err => { if (err) { reject(); } else { resolve(); } }); }); })).then(() => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('All files uploaded and moved!'); res.end(); }).catch(() => { res.writeHead(500, {'Content-Type': 'text/plain'}); res.write('Error uploading files!'); res.end(); }); }); return; } res.writeHead(200, {'Content-Type': 'text/html'}); res.end(` <form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="upload" multiple /> <input type="submit" value="Upload" /> </form> `); }).listen(8080);
这段代码演示了如何在 formidable
模块中使用 multiples
选项解析多个文件上传请求,并使用 Promise 机制在所有文件都上传完成后返回正确的响应。
文件下载
要实现文件下载,我们需要使用 Node.js 内置的 http
模块来发送文件内容给客户端。示例代码如下:
// javascriptcn.com 代码示例 const http = require('http'); const fs = require('fs'); http.createServer((req, res) => { const file = 'downloads/test.pdf'; const stat = fs.statSync(file); const fileSize = stat.size; const range = req.headers.range; if (range) { const parts = range.replace(/bytes=/, "").split("-"); const start = parseInt(parts[0], 10); const end = parts[1] ? parseInt(parts[1], 10) : fileSize-1; const chunksize = (end-start) + 1; const fileStream = fs.createReadStream(file, {start, end}); const headers = { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'application/pdf', }; res.writeHead(206, headers); fileStream.pipe(res); } else { const headers = { 'Content-Length': fileSize, 'Content-Type': 'application/pdf', }; res.writeHead(200, headers); fs.createReadStream(file).pipe(res); } }).listen(8080);
这段代码演示了如何使用 Node.js 的 http
模块来读取本地的 PDF 文件并将其发送给客户端。我们注意到,为了支持断点续传功能,我们需要额外的处理 range
请求头,并使用 206 状态码返回文件的部分内容。
总结
通过本文的学习,我们了解了如何使用 Node.js 进行文件上传与下载操作。在实际应用中,我们可以根据具体业务需求和功能实现要求,对代码进行优化和补充。目前,Node.js 生态系统中有多个针对文件上传、下载的优秀模块,如 multer
、busboy
等,它们都可以非常好地解决文件 IO 相关问题。对于进阶学习,我们可以通过深入研究这些模块的实现原理来提升自己的技术水平。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652ba6297d4982a6ebd6e741