const http = require('http');
const fs = require('fs');
const path = require('path');
const { Buffer } = require('buffer');
// Create a sample file for upload demonstration
const sampleFile = path.join(__dirname, 'upload-sample.txt');
const sampleContent = 'This is a sample file for upload demonstration.\n'.repeat(5);
fs.writeFileSync(sampleFile, sampleContent);
console.log(`Created sample file: ${sampleFile}`);
// Function to generate a multipart form data boundary
function createMultipartFormData(fields, files) {
const boundary = `----NodeJSUpload${Math.random().toString(16).substr(2)}`;
const crlf = '\r\n';
let body = [];
// Add regular fields
Object.entries(fields).forEach(([name, value]) => {
body.push(`--${boundary}${crlf}`);
body.push(`Content-Disposition: form-data; name="${name}"${crlf}${crlf}`);
body.push(`${value}${crlf}`);
});
// Add file fields
Object.entries(files).forEach(([fieldName, filePath]) => {
const filename = path.basename(filePath);
const fileContent = fs.readFileSync(filePath);
body.push(`--${boundary}${crlf}`);
body.push(
`Content-Disposition: form-data; name="${fieldName}"; filename="${filename}"${crlf}`
);
body.push(`Content-Type: application/octet-stream${crlf}${crlf}`);
// Add file content as a buffer
body.push(Buffer.concat([
Buffer.from(body.join(''), 'utf8'),
fileContent,
Buffer.from(crlf, 'utf8')
]));
body = [];
});
// Add final boundary
body.push(`--${boundary}--`);
// Convert to buffer
const bodyBuffer = Buffer.concat([
Buffer.from(body.join(''), 'utf8'),
Buffer.from(crlf, 'utf8')
]);
return {
boundary,
body: bodyBuffer,
headers: {
'Content-Type': `multipart/form-data; boundary=${boundary}`,
'Content-Length': bodyBuffer.length
}
};
}
// Create a test server to handle file uploads
const server = http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/upload') {
let body = [];
let fileData = null;
console.log('\n=== File Upload Received ===');
console.log('Headers:', JSON.stringify(req.headers, null, 2));
req.on('data', (chunk) => {
body.push(chunk);
});
req.on('end', () => {
fileData = Buffer.concat(body);
console.log(`Received ${fileData.length} bytes of file data`);
// Save the uploaded file (in a real app, you'd want to validate and sanitize the filename)
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}
const uploadedFilePath = path.join(uploadDir, `upload-${Date.now()}.txt`);
fs.writeFileSync(uploadedFilePath, fileData);
console.log(`File saved to: ${uploadedFilePath}`);
// Send response
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
status: 'success',
message: 'File uploaded successfully',
file: path.basename(uploadedFilePath),
size: fileData.length,
savedPath: uploadedFilePath
}));
});
} else {
// Serve a simple upload form for testing
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<title>File Upload Test</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.container { background: #f5f5f5; padding: 20px; border-radius: 5px; }
pre { background: #fff; padding: 10px; border: 1px solid #ddd; border-radius: 3px; overflow-x: auto; }
</style>
</head>
<body>
<h1>File Upload Test</h1>
<div class="container">
<h2>Upload a File</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
<div style="margin-bottom: 10px;">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username" value="testuser">
</div>
<div style="margin-bottom: 10px;">
<label for="file">Select file to upload:</label><br>
<input type="file" id="file" name="file">
</div>
<button type="submit">Upload</button>
</form>
</div>
<h2>Or upload programmatically:</h2>
<div class="container">
<p>Run the following command in your terminal:</p>
<pre>curl -F "username=testuser" -F "file=@${sampleFile}" http://localhost:3007/upload</pre>
<p>Or use the Node.js client that's already running in the background.</p>
</div>
</body>
</html>
`);
}
});
// Start the server
const PORT = 3007;
server.listen(PORT, () => {
console.log(`Upload server running at http://localhost:${PORT}`);
// Create a sample upload using the Node.js client
console.log('\n=== Testing file upload with Node.js client ===');
// Prepare form data
const formData = createMultipartFormData(
{
username: 'demo_user',
description: 'Test file upload from Node.js client'
},
{
file: sampleFile
}
);
// Make the upload request
const req = http.request({
hostname: 'localhost',
port: PORT,
path: '/upload',
method: 'POST',
headers: {
...formData.headers,
'User-Agent': 'Node.js File Upload Demo'
}
}, (res) => {
console.log(`\nUpload Response Status: ${res.statusCode} ${res.statusMessage}`);
console.log('Response Headers:', JSON.stringify(res.headers, null, 2));
let responseData = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
try {
const result = JSON.parse(responseData);
console.log('Upload Result:', JSON.stringify(result, null, 2));
// Clean up the sample file
if (fs.existsSync(sampleFile)) {
fs.unlinkSync(sampleFile);
console.log('\nCleaned up sample file');
}
console.log('\nYou can now visit http://localhost:3007 in your browser to test the upload form.');
console.log('Press Ctrl+C to stop the server.');
} catch (e) {
console.error('Error parsing upload response:', e);
console.log('Raw response:', responseData);
}
});
});
req.on('error', (e) => {
console.error(`Upload error: ${e.message}`);
// Clean up the sample file on error
if (fs.existsSync(sampleFile)) {
fs.unlinkSync(sampleFile);
}
server.close();
});
// Send the form data
req.write(formData.body);
req.end();
});
// Handle server errors
server.on('error', (err) => {
console.error('Server error:', err);
// Clean up the sample file on error
if (fs.existsSync(sampleFile)) {
fs.unlinkSync(sampleFile);
}
});
// Handle process termination
process.on('SIGINT', () => {
console.log('\nShutting down server...');
// Clean up the sample file on exit
if (fs.existsSync(sampleFile)) {
fs.unlinkSync(sampleFile);
}
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});