UEditor+nodejs+seaweedfs图片服务器搭建
参考链接:
http://blog.coinidea.com/web%E5%BC%80%E5%8F%91/nodejs-1161.html
1. UEditor+nodejs图片上传
UEditor是百度开源的富文本编辑器,功能比较强大。
下载地址是:http://ueditor.baidu.com/website/download.html
目前提供:PHP、ASP、.Net、JSP版本。UEditor主要是以前端HTML、CSS、JS为主的,之所以按各种动态语言再细分版本,我的理解是主要是在图片上传这一涉及到与服务器交互的功能上。
在众多版本中,没有提供nodejs的版本,下面将介绍如何用PHP版本的UEditor改造成nodejs版本的UEditor。
咨询查看PHP版本的所有请求,发现action参数值包括config(配置文件)、uploadimage(图片上传)、listimage(在线管理)、catchimage(抓取图片),所以只需要重写这4个请求就基本上实现了我们的需求。
1.1 修改UEditor的ueditor.config.js的serverUrl属性:
serverUrl: '/ue/uploads'
1.2 将ueditor/php/config.json文件名修改为config.js并移动到ueditor目录下。
1.3 接下来主要在nodejs端编写对应的四个action就好,图片上传使用了connect-busboy中间件。代码如下:
// 图片上传
var path = require('path');
var uploadsPath = path.resolve('public/uploads') + '/';//存储图片的路径
var busboy = require('connect-busboy');
app.use(busboy({
limits: {
fileSize: 10 * 1024 * 1024 // 10MB
}
}));
var action = {
/// 上传图片
uploadimage: function (req, res) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
var filesize = 0;
var ext = path.extname(filename);
var newFilename = (new Date() - 0) + ext;
fstream = fs.createWriteStream(uploadsPath + newFilename);
file.on('data', function (data) {
filesize = data.length;
});
fstream.on('close', function () {
console.log(JSON.stringify({
"originalName": filename,
"name": newFilename,
"url": '/uploads/' + newFilename,
"type": ext,
"size": filesize,
"state": "SUCCESS"
}));
res.send(JSON.stringify({
"originalName": filename,
"name": newFilename,
"url": '/uploads/' + newFilename,
"type": ext,
"size": filesize,
"state": "SUCCESS"
}));
});
file.pipe(fstream);
});
},
/// 获取配置文件
config: function (req, res) {
return res.redirect('/js/UEditor/config.js');
},
/// 在线管理
listimage: function (req, res) {
fs.readdir(uploadsPath, function (err, files) {
var total = 0, list = [];
files.sort().splice(req.query.start, req.query.size).forEach(function (a, b) {
/^.+.\..+$/.test(a) &&
list.push({
url: '/uploads/' + a,
mtime: new Date(fs.statSync(uploadsPath + a).mtime).getTime()
});
});
total = list.length;
res.json({state: total === 0 ? 'no match file' : 'SUCCESS', list: list, total: total, start: req.query.start});
});
},
/// 抓取图片(粘贴时将图片保存到服务端)
catchimage: function (req, res) {
var list = [];
req.body.source.forEach(function (src, index) {
http.get(src, function (_res) {
var imagedata = '';
_res.setEncoding('binary');
_res.on('data', function (chunk) {
imagedata += chunk
});
_res.on('end', function () {
var pathname = url.parse(src).pathname;
var original = pathname.match(/[^/]+\.\w+$/g)[0];
var suffix = original.match(/[^\.]+$/)[0];
var filename = Date.now() + '.' + suffix;
var filepath = uploadsPath + 'catchimages/' + filename;
fs.writeFile(filepath, imagedata, 'binary', function (err) {
list.push({
original: original,
source: src,
state: err ? "ERROR" : "SUCCESS",
title: filename,
url: '/uploads/catchimages/' + filename
});
})
});
})
});
var f = setInterval(function () {
if (req.body.source.length === list.length) {
clearInterval(f);
res.json({state: "SUCCESS", list: list});
}
}, 50);
}
};
app.get('/ue/uploads',function (req, res) {
action[req.query.action](req, res);
});
app.post('/ue/uploads', function (req, res) {
action[req.query.action](req, res);
});
以上主要参考了博客:http://www.xiaoboy.com/detail/1341545081.html
2. GoLang的安装与配置
1中UEditor的图片上传到哪儿nodejs服务器中的/public/uploads/文件夹中,如果需要高存储、可移植、可扩展等特性的图片服务器,则需要配置专门的服务器。本文选用的是开源的图片(文件)分布式服务器seaweedfs。
Github地址:https://github.com/chrislusf/seaweedfs
该服务器使用GoLang编写,所以需要安装配置GoLang。中国的下载地址:http://www.golangtc.com/download,根据自己的操作系统选择特定的包下载即可。本文演示的windows7 x64下载安装。傻瓜式安装好之后,需要配置一下环境变量:
GOROOT=D:\Go16
GOPATH=D:\ImageServer\seaweedfs
PATH=D:\Go16\bin
GOPATH环境变量,这个变量很重要,我自己写的代码要放到这个变量中配置的目录中,go编译器才会找到并编译
3. seaweedfs的编译运行
Github上吧seaweedfs的代码clone下来,然后安装makefile中的执行也可以直接直接makefile。在seaweedfs中执行控制台:
go clean -i -v ./go/weed/
#rm –f weed #for linux
go get -v –d ./go/weed
go build -v -o weed ./go/weed
其中在get依赖的时候有可能有些依赖包不能下载,需要自己手动下载,放入:\seaweedfs\src目录中。
推荐一个go下载包地址:https://gopm.io/download?pkgname=golang.org/x/net
Buid之后会在seaweedfs中生成一个weed,也可以将其改名为weed.exe。这个时候就可以启动weed。以本机为演示:
weed master
image
weed volume –dir=”./tmp/data1” –max=5 –mserver=”localhost:9333” –port=8080 &
[![image](https://img.haomeiwen.com/i13720662/4e045e11d550fd66.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "image003")](http://devhu-wordpress.stor.sinaapp.com/uploads/2016/05/image0031.png)
按照github的描述上传、下载图片都没有问题。至此基本的图片服务器搭建完成。
修改nodejs的图片上传代码如下:
// 图片上传
var path = require('path');
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
function curlPostAssign(res, filepath, filename, filesize) {
request.post(config.url_image + 'dir/assign',{},
function (error, response, body) {
if (!error && response.statusCode == 200) {
assign = eval('(' + body + ')');
var result = {};
result.res = res;
result.json = JSON.stringify({
"originalName": filename,
"name": assign.fid,
"url": '/res?fid=' + assign.fid,
"type": ext,
"size": filesize,
"state": "SUCCESS"
});
curlPostWrite(assign.fid, filepath, assign.publicUrl, result);
var ext = path.extname(filename);
}else{
console.log("Image server assign error...")
}
});
}
function curlPostWrite(fid, tmp_file, publicUrl, result) {
var files = [
{urlKey: "file1", urlValue: tmp_file}
]
var options = {
host: publicUrl.split(":")[0] ,
port: publicUrl.split(":")[1] ,
method: "POST",
path: "/" + fid
}
var req = http.request(options, function(res){
//res.setEncoding("utf8");
res.on("data", function(chunk){
//console.log("BODY:" + chunk);
})
})
req.on('error', function(e){
console.log('problem with request:' + e.message);
console.log(e);
})
postfile.postFile(files, req, result);
}
var action = {
/// 上传图片
uploadimage: function(req, res) {
curlPostAssign(res, req.files.upfile.path, req.files.upfile.originalFilename, req.files.upfile.size);
},
/// 获取配置文件
config: function (req, res) {
return res.redirect('/js/UEditor/config.js');
},
/// 在线管理
listimage: function (req, res) {
fs.readdir(uploadsPath, function (err, files) {
var total = 0, list = [];
files.sort().splice(req.query.start, req.query.size).forEach(function (a, b) {
/^.+.\..+$/.test(a) &&
list.push({
url: '/uploads/' + a,
mtime: new Date(fs.statSync(uploadsPath + a).mtime).getTime()
});
});
total = list.length;
res.json({state: total === 0 ? 'no match file' : 'SUCCESS', list: list, total: total, start: req.query.start});
});
},
/// 抓取图片(粘贴时将图片保存到服务端)
catchimage: function (req, res) {
var list = [];
req.body.source.forEach(function (src, index) {
http.get(src, function (_res) {
var imagedata = '';
_res.setEncoding('binary');
_res.on('data', function (chunk) {
imagedata += chunk
});
_res.on('end', function () {
var pathname = url.parse(src).pathname;
var original = pathname.match(/[^/]+\.\w+$/g)[0];
var suffix = original.match(/[^\.]+$/)[0];
var filename = Date.now() + '.' + suffix;
var filepath = uploadsPath + 'catchimages/' + filename;
fs.writeFile(filepath, imagedata, 'binary', function (err) {
list.push({
original: original,
source: src,
state: err ? "ERROR" : "SUCCESS",
title: filename,
url: '/uploads/catchimages/' + filename
});
})
});
})
});
var f = setInterval(function () {
if (req.body.source.length === list.length) {
clearInterval(f);
res.json({state: "SUCCESS", list: list});
}
}, 50);
}
};
app.get('/ue/uploads',multipartMiddleware, function (req, res) {
action[req.query.action](req, res);
});
app.post('/ue/uploads',multipartMiddleware, function (req, res) {
action[req.query.action](req, res);
});
image
image
参考链接:
http://blog.coinidea.com/web%E5%BC%80%E5%8F%91/nodejs-1161.html