前端开发那些事让前端飞Web前端之路

上传图片: vue + axios + express

2018-04-24  本文已影响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.

上一篇下一篇

猜你喜欢

热点阅读