首页 » Web开发 » 正文

[nodejs]UEditor+nodejs+seaweedfs图片服务器搭建

  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);</p>

<pre><code>}
</code></pre>

<p>};
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/</p>

<h1>rm –f weed #for linux</h1>

<p>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

weed volume –dir=”./tmp/data1” –max=5 –mserver=”localhost:9333” –port=8080 &

按照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 &amp;&amp; response.statusCode == 200) {
                assign = eval('(' + body + ')');
                var result = {};
                result.res = res;
                result.json = JSON.stringify({
                    &quot;originalName&quot;: filename,
                    &quot;name&quot;: assign.fid,
                    &quot;url&quot;: '/res?fid=' + assign.fid,
                    &quot;type&quot;: ext,
                    &quot;size&quot;: filesize,
                    &quot;state&quot;: &quot;SUCCESS&quot;
                });
                curlPostWrite(assign.fid, filepath, assign.publicUrl, result);
                var ext = path.extname(filename);
            }else{
                console.log(&quot;Image server assign error...&quot;)
            }
        });
}
function curlPostWrite(fid, tmp_file, publicUrl, result) {
    var files = [
        {urlKey: &quot;file1&quot;, urlValue: tmp_file}
    ]
    var options = {
        host: publicUrl.split(&quot;:&quot;)[0] ,
        port: publicUrl.split(&quot;:&quot;)[1] ,
        method: &quot;POST&quot;,
        path: &quot;/&quot; + fid
    }</p>

<pre><code>var req = http.request(options, function(res){
    //res.setEncoding(&amp;quot;utf8&amp;quot;);
    res.on(&amp;quot;data&amp;quot;, function(chunk){
        //console.log(&amp;quot;BODY:&amp;quot; + chunk);
    })
})

req.on('error', function(e){
    console.log('problem with request:' + e.message);
    console.log(e);
})
postfile.postFile(files, req, result);
</code></pre>

<p>}
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) {
                /^.+.&#46;.+$/.test(a) &amp;&amp;
                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(/[^/]+&#46;\w+$/g)[0];
                    var suffix = original.match(/[^&#46;]+$/)[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 ? &quot;ERROR&quot; : &quot;SUCCESS&quot;,
                            title: filename,
                            url: '/uploads/catchimages/' + filename
                        });
                    })
                });
            })
        });
        var f = setInterval(function () {
            if (req.body.source.length === list.length) {
                clearInterval(f);
                res.json({state: &quot;SUCCESS&quot;, list: list});
            }
        }, 50);</p>

<pre><code>}
</code></pre>

<p>};
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);
});

运行效果:

本文共 4 个回复

发表评论