Skip to content

Instantly share code, notes, and snippets.

@azzgo
Created June 23, 2018 05:20
Show Gist options
  • Save azzgo/76e513bd45e4bf2e4330f74bb3f857d8 to your computer and use it in GitHub Desktop.
Save azzgo/76e513bd45e4bf2e4330f74bb3f857d8 to your computer and use it in GitHub Desktop.
simple upload node server without 3rd library
// some code from <https://stackoverflow.com/questions/46629086/node-js-file-upload-server-without-third-party-module>
var http = require('http');
var fs = require('fs')
var buffer = require('buffer')
function parseForm(boundary, data){
var form = {};
var delimiter = Buffer.from("\r\n--" + boundary);
var body = extract(data, "--" + boundary + "\r\n");
var CR = Buffer.from("\r\n\r\n");
var i = 0;
var head;
var name;
var filename;
var value;
var obj;
if (body) {
while (i !== -1){
[head, i] = extract(body, i, CR);
name = extract(head, '; name="', '"').toString();
filename = extract(head, '; filename="', '"').toString();
[value, i] = extract(body, i, delimiter);
if (name){
obj = filename ? {filename, value} : {value};
if (form.hasOwnProperty(name)){ // multiple
if (Array.isArray(form[name])){
form[name].push(obj);
} else {
form[name] = [form[name], obj];
}
} else {
form[name] = obj;
}
}
if (body[i] === 45 && body[i + 1] === 45) break; // "--"
if (body[i] === 13 && body[i + 1] === 10){
i += 2; // "\r\n"
} else {
//error
}
}
}
return form;
}
function extract(arr, start, end){
if (!arr) {
return
}
var useIndex = typeof start === "number",
i,
j;
if (useIndex){
i = start;
if (end){
j = arr.indexOf(end, i);
return (j === -1) ? ["", -1] : [ (i === j) ? "" : arr.slice(i, j), j + end.length];
} else return arr.slice(i);
} else {
i = arr.indexOf(start);
if (i !== -1){
i += start.length;
if (end){
j = arr.indexOf(end, i);
if (j !== -1) return arr.slice(i, j);
} else return arr.slice(i);
}
return "";
}
}
http
.createServer(function(req, res) {
if (
req.url === '/upload'
&&
req.method === 'POST'
&&
req.headers['content-type'].indexOf('multipart/form-data') > -1
) {
let boundary = req.headers['content-type'].match(/boundary=(.*)/)[1]
let data = new buffer.Buffer(parseInt(req.headers['content-length'], 10))
let pos = 0
req.on('data', chunk => {
data.fill(chunk, pos)
pos += chunk.length
})
req.on('end', () => {
var parseData = parseForm(boundary, data)
var file = parseData.file
fs.createWriteStream(file.filename).end(file.value)
res.end('ok');
});
} else {
// show a file upload form
res.writeHead(200, { 'content-type': 'text/html' });
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">' +
'<input type="file" name="file" multiple="multiple"><br>' +
'<input type="submit" value="Upload">' +
'</form>'
);
}
})
.listen(8080);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment