美文网首页
如何将 vue-quill-editor 图片上传到服务器

如何将 vue-quill-editor 图片上传到服务器

作者: 原来是禽兽 | 来源:发表于2019-02-15 11:58 被阅读0次

    vue-quill-editor 默认将图片转为base64。
    这样很方便,但是有个致命的问题:
    大图片转base64后会非常非常非常。。。的。。。长。。。
    如果将带有这种图片的文本保存到数据库后就会发现:
    整个表的查询时间会非常非常非常。。。的。。。长。。。
    我不是做后端的,用的是node + mongodb。实际将一个4.7M的图片转base64后存入数据库,会直接导致查询超时。至于其他语言、其他数据库会不会有同样的问题就不清楚了。

    我的解决办法就是修改quill的默认上传功能。
    先看一下实际效果:


    image.png

    在项目的npm包目录中找到quill模块,修改dist文件夹下的quill.js。
    大概在6780行附近,可以找到下面这段代码:

    if (fileInput == null) {
        fileInput = document.createElement('input');
        fileInput.setAttribute('type', 'file');
        fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon');
        fileInput.classList.add('ql-image');
        fileInput.addEventListener('change',  () => {
            if (fileInput.files != null && fileInput.files[0] != null) {
                //  自定义图片上传功能
                var formData = new FormData();
                formData.append('upload', fileInput.files[0]);
                var xhr = new XMLHttpRequest();
                xhr.open('post', 'http://localhost:8082/upload');
                xhr.withCredentials = true;
                xhr.responseType = 'json';
                xhr.send(formData);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        var range = _this3.quill.getSelection(true);
                        _this3.quill.updateContents(new _quillDelta2.default().retain(range.index).delete(range.length).insert({ image: 'http://localhost:8082' + xhr.response.path }), _emitter2.default.sources.USER);
                    }
                };
    
                //  -----------------  这里是自定义上传与默认上传的分界线 ------------------
    
                // var reader = new FileReader();
                // reader.onload = function (e) {
                //     var range = _this3.quill.getSelection(true);
                //     _this3.quill.updateContents(new _quillDelta2.default().retain(range.index).delete(range.length).insert({ image: e.target.result }), _emitter2.default.sources.USER);
                //     _this3.quill.setSelection(range.index + 1, _emitter2.default.sources.SILENT);
                //     // fileInput.value = "";
                // };
                // reader.readAsDataURL(fileInput.files[0]);
            }
        });
        this.container.appendChild(fileInput);
    }
    

    上面代码中,注释的部分就是quill默认的图片上传。
    我将它改为直接将图片上传到服务器。

    当然这需要服务端做一些配合,下面是服务端的代码:

    app.post('/upload', (req, res) => {
        var uploadDir = "/fileupload/" + req.session.username;
        var form = new formidable.IncomingForm();
        form.uploadDir = uploadDir;
        //  是否保留上传文件拓展名
        form.keepExtensions = true;
        form.hash = 'md5';
    
        function uploadCallback(err, fields, files) {
            var file = files.upload;
            //  给已上传文件的MD5值做持久化保存
            //  每次上传可以查询当前用户下,是否有相同文件。如果有把本次上传文件删除,返回数据库中文件地址。
            fileUploadModel.findOne({hash: file.hash, user: req.session.username}).then(fileUpload => {
                if( fileUpload ) {
                    console.log('发现相同文件!');
                    fs.unlink(file.path, () => {
                        file.path = fileUpload.path;
                        res.send(file)
                    });
                } else {
                    console.log('添加文件');
                    fileUploadModel.create({
                        path: file.path,
                        hash: file.hash,
                        user: req.session.username
                    }, err => {
                        res.send(file);
                    })
                }
            })
        }
    
        //  判断上传文件路径是否存在,不存在先创建再上传
        fs.access(uploadDir, err => {
            if( err ) {
                fs.mkdir(uploadDir, err => {
                    form.parse(req, uploadCallback);
                });
            } else {
                form.parse(req, uploadCallback);
            }
        });
    })
    

    其实服务器要做的就是返回完整的文件描述。
    其中包含文件大小、服务器静态地址、名称等等。
    以下内容逐渐脱离标题。。。
    这里之所以代码比较多的原因是我做了额外的一些处理。
    后台上传我用了formidable,功能够用,自带MD5加密。

    1. 对不同用户做了文件路径的分类,并不是将所有文件保存在同一个目录下。这样可能便于后期的管理。所以要先判断当前用户是否有自己的文件夹,没有就先创建。
    2. 将上传的文件MD5做持久化保存,目的是对相同文件进行去重,节省服务器空间。如果上传的文件之前上传过,会从数据库中直接拿以前的文件地址,并删除最新上传的文件。

    相关文章

      网友评论

          本文标题:如何将 vue-quill-editor 图片上传到服务器

          本文链接:https://www.haomeiwen.com/subject/tlrpeqtx.html