示例代码:
const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');
// 设置公开目录
const publicDir = path.join(__dirname, 'public');
const uploadDir = path.join(publicDir, 'uploads');
// 检查并创建 uploads 文件夹
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
console.log('Uploads directory created.');
}
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url, true);
// 处理文件上传
if (req.method === 'POST' && parsedUrl.pathname === '/upload') {
const chunks = [];
let boundary;
// 获取请求头中的 boundary
const contentType = req.headers['content-type'];
if (contentType && contentType.startsWith('multipart/form-data')) {
boundary = contentType.split('boundary=')[1];
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Invalid content type');
return; // 提前退出
}
// 接收数据
req.on('data', (chunk) => { chunks.push(chunk); });
req.on('end', () => {
const body = Buffer.concat(chunks); // 将数据块合并为完整的 Buffer
const boundaryBuffer = Buffer.from(`--${boundary}`);
// 分割请求体
const parts = splitBuffer(body, boundaryBuffer);
let fileSaved = false;
parts.forEach((part) => {
if (part.includes('filename=')) {
// 提取文件名
const header = part.toString().split('\r\n\r\n')[0];
const filenameMatch = header.match(/filename="(.+)"/);
if (!filenameMatch) {
if (!fileSaved) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Filename not found');
}
return; // 提前退出
}
const filename = filenameMatch[1];
// 提取文件数据
const fileData = part.slice(part.indexOf('\r\n\r\n') + 4, part.lastIndexOf('\r\n'));
// 保存文件
const filePath = path.join(uploadDir, filename);
fs.writeFileSync(filePath, fileData);
console.log(`File saved: ${filePath}`);
fileSaved = true;
// 返回图片的访问 URL
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
message: 'File uploaded successfully',
url: `http://localhost:3000/uploads/${filename}`
}));
}
});
if (!fileSaved) {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('No file uploaded');
}
});
}else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
/**
* 使用指定的分隔符分割 Buffer
* @param {Buffer} buffer - 要分割的 Buffer
* @param {Buffer} delimiter - 分隔符 Buffer
* @returns {Buffer[]} - 分割后的 Buffer 数组
*/
function splitBuffer(buffer, delimiter) {
const result = [];
let start = 0;
let index = 0;
while ((index = buffer.indexOf(delimiter, start)) !== -1) {
if (start !== index) {
result.push(buffer.slice(start, index));
}
start = index + delimiter.length;
}
if (start < buffer.length) {
result.push(buffer.slice(start));
}
return result;
}
server.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});