一、图片上传问题的总结
这个问题纠结了我整整一天的时间,啊,终于在我的疯狂阅读官方文档和博客下,找到了解决办法,现在将整个图片上传至服务器的方法记录如下:
1、流程思路
客户端将图片上传至服务器,服务器会返回给你一个图片的访问路径,这时图片已经存储在了服务端,我们可以通过这个地址去访问它。而我们要处理的问题就是如何将文件对象传递给服务端,并接收到服务端返回给我们的访问地址。
2、使用到的技术
2.1、 前端我使用的是 vue 和 element-ui 中的upload上传容器。代码如下:
<el-form-item label="首图上传">
<el-upload
action="/node/adminUser/imgUpload"
list-type="picture-card"
:on-success="handleAvatarSuccess"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
name="img"
:headers="headers"
>
//如果上传成功,后端会传来一个路径,将这个路径动态绑定,便可以显示你上传的图片
<img v-if="imageUrl" :src="imageUrl" class="avatar" />;
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
-
action 是你访问的后端接口,根据你自己的需求规定。
-
list-type 图片上传容器的样式。(自己可以详读读 element-ui 中的相关文档,配置相应的参数)
-
on-success 是上传图片成功后绑定的一个函数。函数如下:
handleAvatarSuccess(res) {
console.log(res);
this.imageUrl = res.data.path;
this.ruleform.dialogImageUrl = res.data.path;
},
-
show-file-list 是是否显示已上传文件列表。
-
before-upload 是上传图片前的一个校验函数,用于判断图片的格式大小是否符合规格。函数如下:(这里大家可以根据自己的需求来限制图片上传的规格)
beforeAvatarUpload(file) {
const isJPG = file.type === "image/jpeg";
const isPNG = file.type === "image/png";
const isLt3M = file.size / 1024 / 1024 / 1024 < 3;
if (!isJPG && !isPNG) {
this.$message.error("上传头像图片只能是 JPG 格式或 png 格式!");
}
if (!isLt3M) {
this.$message.error("上传头像图片大小不能超过 3MB!");
}
return isJPG && isLt3M;
},
-
name 这个参数特别关键,官方文档解释说它是上传的文件字段名 。这个参数是我们后端接收图片时要用的一个参数,用于辨识你的图片信息。个人理解是这个容器上传的底层可能用到了 FormData 这个对象的缘故,所以会用到name这个字段。
-
headers 是上传的请求头,必须要设置,不然后端无法接收到对应的文件对象参数。
headers:{ enctype: "multipart/form-data"},
至此,前端的所有配置已完毕。接下来重要的部分来了,后端接收前端的传输的图片,发送给前端访问地址。
2.2 、后端我使用的是 node.js 来接收并处理图片文件信息。
-
安装 multer
npm install --save multer
-
创建服务,并引入你的路由接口
const express = require("express");
const app = express();
const cors = require("cors")
app.use(cors({ origin: "http://localhost:8080" }))
app.use(express.static("./public"))
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
require("./module/mongoose/mongoose")
app.use(require("./module/plugin_vue/session"))
app.use("/adminUser", require("./router/amdinUser"))
app.listen("80", () => {
console.log("80端口启动成功");
})
-
amdinUser 文件中的子路由
const express = require("express");
const router = express.Router();
const multer = require("multer")
const storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./public/vue_img/blogImg")
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}-${file.originalname}`)
}
})
const upload = multer({ storage: storage })
router.post("/imgUpload", upload.array("img", 1), (req, res) => {
let file = req.files;
console.log(file[0]);
let fileInfo = {}
fileInfo.type = file[0].mimetype;
fileInfo.name = file[0].originalname;
fileInfo.size = file[0].size;
fileInfo.path = '/node/vue_img/blogImg/' + file[0].filename;
res.send({
code: 0,
value: "图片上传成功",
data: fileInfo
})
})
module.exports = router;
说明:
- 这里的 upload.array("img",1) 中的 img 就是 el-upload 容器中的 name (上传文件的头部信息)名称,1代表的是上传的文件个数。如果是单个文件,官方文档说明中也可以使用 upload.single("img"),但是我试了好几次没成功,el-upload也设置了只能上传单个文件也无法生效,建议使用upload.array()。
- 在路由接口中使用 req.files 获取前端发送的文件对象信息,最后封装我们要返回给前端的图片访问地址。
3、效果展示
-
前端界面成功请求服务端的图片并显示

-
服务端已经在相应目录下增加了此图片。
