上传图片: vue + axios + express

作者: 柳正来 | 来源:发表于2018-04-24 12:38 被阅读104次

    上传图片到服务器是一个很常见的需求, 应该实现起来很简单. 但是之前没这方面经验, 折腾了一番.

    调研

    数据库中应该只保存图片的链接, 图片保存在文件系统中, 可以是服务器本地, 可以是自己部署的独立图片服务器, 也可以是第三方服务器.

    MongoDB中, BSON文件的上显示16MB. 所以如果图片不超过这个上限, 就可以存BSON; 否则要用GridFS.

    对我来说, 最理想的当然是使用第三方图片服务器了. 但是现在并不想花这个钱(囧rz). 所以想先试试存在自己的服务器本地.

    界面怎么写?

    上传文件有个专门的控件, input[type="file"]. 浏览了几个网站的实现, 都是把input[type="file"]隐藏起来(因为它太丑), 然后在相同的区域摆上一个按钮之类的东西(好看一些), 用户点了按钮其实点击了input[type="file"].

    示例如下:

    <label class="btn btn-primary file-chooser">
        Change Picture
      <input type="file" accept=".jpg, .jpeg, .png" @change="uploadAvatar">
    </label>
    
    upload avatar

    input[type="file"]支持属性accept, 上面的代码只接受.jpg, .jpeg, .png文件.

    @change="uploadAvatar"是vue中监听input[type="file"]change事件. 用户选择的图片会成为e.target.files[0].

    uploadAvatar(e) {
      service.uploadAvatar(e.target.files[0]);
    }
    

    请求怎么发?

    我用的是axios处理请求. 搜了一下需要用multipart/form-datacontent-type发送, 具体如下:

    // service.js
    uploadAvatar(avatar) {
        let data = new FormData();
        data.append('avatar', avatar);
        return axios.post('/upload-avatar', data, {
            headers: { 'content-type': 'multipart/form-data' }
        });
    }
    

    后端怎么接?

    我用的是express + mongodb. 其实我本来打算存BSON的, 反正头像不用16MB那么大.

    但是搜了一下可以用multer, 阴差阳错存到本地了.

    npm install -S multer后:

    // index.js
    const multer = require('multer');
    const avatarUpload = multer({ dest: 'public/avatar/' });
    
    app.use(express.static('public'));
    

    第二行创建了文件夹public/avatar作为存储图片的地点.
    第三行是将整个public文件夹都作为静态资源, 让外部可以访问.

    然后写路由:

    router.post(
        '/upload-avatar',
        authenticator,
        avatarUpload.single('avatar'),
        (req, res) => {
            // Set { new: true } to return the updated one, rather than the original one.
            User.findByIdAndUpdate(req.user.id, { avatar: req.file.path }, { new: true }).then(user => {
                res.json({ message: "ok" });
            });
        }
    );
    

    authenticator是我在JWT上手: Express+Passport做的用户身份JWT验证逻辑, 此处请忽略. 示例代码里面没删除是因为req.user.id需要它.

    avatarUpload.single('avatar')引入了multer的中间件, 读取请求中的key为avatar的文件, 返回到req.file中. req.file是一个object, 里面有mimetype等信息, 我们需要的是req.file.path, 即服务器本地的地址.

    User.findByIdAndUpdate就是把这条信息更新到mongoDB中.

    至此, 打完收工.

    回头来看, 感觉真简单. 但是调研的时候接触到了很多听都没听过的东西, BSON, GridFS, multer, 充满不确定性 :P.

    相关文章

      网友评论

        本文标题:上传图片: vue + axios + express

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