Node.js服务器:图像上传/损坏问题
Node.js Server: Image Upload / Corruption Issues
所以我试图在Node.js中编写一个基本的文件服务器,我尝试上传和存储的所有图像都被破坏了。这个问题似乎与节点缓冲区处理转换为UTF-8并再次转换的方式有关(我必须这样做才能将POST正文标头从二进制数据中取出)。
这里有一个简单的Node服务器,它显示了我目前的方法和我一直遇到的问题:
var http = require('http');
var server = http.createServer(function(request, response) {
if (request.method === "GET") {
// on GET request, output a simple web page with a file upload form
var mypage = '<!doctype html><html><head><meta charset="utf-8">' +
'<title>Submit POST Form</title></head>'r'n<body>' +
'<form action="http://127.0.0.1:8008" method="POST" ' +
'enctype="multipart/form-data"> <input name="upload" ' +
'type="file"><p><button type="submit">Submit</button>' +
'</p></form></body></html>'r'n';
response.writeHead(200, {
"Content-Type": "text/html",
"Content-Length": mypage.length
});
response.end(mypage);
} else if (request.method === "POST") {
// if we have a return post request, let's capture it
var upload = new Buffer([]);
// get the data
request.on('data', function(chunk) {
// copy post data
upload = Buffer.concat([upload, chunk]);
});
// when we have all the data
request.on('end', function() {
// convert to UTF8 so we can pull out the post headers
var str = upload.toString('utf8');
// get post headers with a regular expression
var re = /('S+)'r'nContent-Disposition:'s*form-data;'s*name="'w+";'s*filename="[^"]*"'r'nContent-Type: ('S+)'r'n'r'n/i,
reMatch = str.match(re);
var lengthOfHeaders = reMatch[0].length,
boundary = reMatch[1],
mimeType = reMatch[2];
// slice headers off top of post body
str = str.slice(lengthOfHeaders);
// remove the end boundary
str = str.replace("'r'n" + boundary + "--'r'n", '');
// convert back to buffer
var rawdata = new Buffer(str, 'utf8');
// echo back to client
response.writeHead(200, {
"Content-Type": mimeType
});
response.end(rawdata);
});
}
});
server.listen(8008);
console.log("server running on port 8008");
要测试它,请在节点中运行脚本,然后在浏览器中转到127.0.0.1:8008。尝试上传图像并提交表单。每次图像都会损坏,即使脚本应该直接将图像数据回显到浏览器。
有人知道我在这里做错了什么吗?有没有更好的方法来处理Node中我还没有弄清楚的POST正文标头?(在任何人说任何话之前,不,我不想使用Express。我想弄清楚并理解这个问题。)
这个问题似乎与节点缓冲区处理转换为UTF-8并返回的方式有关
我想你是对的,转换为UTF-8是个坏主意,但可以这样做只是为了处理文件并获取标题和边界位置,但保持缓冲区文件不变,当你有了所有位置可以从文件中获取标题和边缘时,只需将缓冲区复制到像这样的新缓冲区
originalBuffer.copy(newBuffer,0,positionHeader,positionEndBoundary)
var http = require('http');
var fs = require('fs');
var connections = 0;
var server = http.createServer(function (req, res) {
connections++;
console.log(req.url,"connections: "+connections);
if(req.url == '/'){
res.writeHead(200, { 'content-type': 'text/html' });
res.end(
'<form action="/upload" enctype="multipart/form-data" method="post">' +
'<input type="file" name="upload" multiple="multiple"><br>' +
'<input type="submit" value="Upload">' +
'</form>'
);
}
var body = new Buffer([]);
if (req.url == '/upload') {
req.on('data', function (foo) {
//f.write(foo);
body = Buffer.concat([body,foo]);
if(isImage(body.toString())){
console.log("é imagem do tipo "+isImage(body.toString()));
}
else{
console.log("Não é imagem");
res.end("Não é imagem");
}
console.log(body.length, body.toString().length);
});
req.on('end', function () {
// console.log(req.headers);
//I converted the buffer to "utf 8" but i kept the original buffer
var str = body.toString();
console.log(str.length);
imageType = isImage(body.toString());
//get the index of the last header character
//I'm just using the string to find the postions to cut the headers and boundaries
var index = str.indexOf(imageType)+(imageType+"'r'n'r'n").length;
// var headers= str.slice(0,index).split(';');
// console.log(headers);
//Here comes the trick
/*
*I have to cut the last boundaries, so i use the lastIndexOf to cut the second boundary
* And maybe that is the corruption issues, because, I'm not sure, but I guess
* the UTF-8 format only use 7bits to represent all characters, and the buffer can use 8bits, or two hex,
*So, i need to take the difference here (body.length-str.length)
*/
var indexBoundayToBuffer = str.lastIndexOf('------WebKitFormBoundary')+(body.length-str.length);
console.log(index, indexBoundayToBuffer);
//maybe you can change this to use less memory, whatever
var newBuffer = Buffer.alloc(body.length);
/*
*And now use the index, and the indexBoudayToBuffer and you will have only the binary
*/
body.copy(newBuffer,0,index,indexBoundayToBuffer);
// f.end();
//file type
var type = imageType.substr("image/".length);
console.log("END");
fs.writeFile("nameFile."+type,newBuffer,function(err,ok){
if(err){
console.log(err);
return false;
}
res.end();
});
});
}
});
function isImage(str){
if(str.indexOf('image/png')!=-1) return 'image/png';
else if(str.indexOf('image/jpeg')!=-1) return 'image/jpeg';
else if(str.indexOf('image/bmp'!=-1)) return 'image/bmp';
else if(str.indexOf('image/gif'!=-1)) return 'image/gif';
else false;
}
var port = process.env.PORT || 8080;
server.listen(port, function () {
console.log('Recording connections on port %s', port);
});
您真的不应该使用这样的正则表达式来解析多部分有效载荷,因为这很容易使解析图像数据变得非常不可靠。npm上有一些模块可以为您解析表单,例如busboy、multiparty或awebrade。它们都不使用正则表达式,也不需要Express。
相关文章:
- 在指令控制器中使用$attrs时出现问题
- 将PHP变量传递给jQuery时遇到问题
- Canvas Html5绘图应用程序,移动画布会导致重大问题
- 参数变量出现ngTable指令问题
- 剑道网格jQuery动画()问题
- 我的jQuery插件参数没有正确启动,遇到了问题
- Phonegap-(安卓/iphone)多个图像的图像库出现问题
- TableExport jquery插件:文件名和扩展名问题
- JavaScript Pub/Sub属性访问问题
- JavaScript异步问题
- 如何解决Yii中的页面刷新问题
- Safari(Mac OS)上的jQuery平滑滚动问题
- jqGrid树网格问题
- 使用正则表达式评估电子邮件地址时出现性能问题
- 如何消除代码中的未定义和其他问题
- JavaScript代码问题:我正在将对象转换为数组
- 三星智能电视应用程序;Brightcove示例应用程序远程控制问题
- 由于iframe导致的问题
- ReactJS和SpringDataRest缓存问题可能与websocket有关
- Node.js服务器:图像上传/损坏问题