一、图片上传问题的总结
这个问题纠结了我整整一天的时间,啊,终于在我的疯狂阅读官方文档和博客下,找到了解决办法,现在将整个图片上传至服务器的方法记录如下:
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>
- 参数解释1 action 是你访问的后端接口,根据你自己的需求规定。 2 list-type 图片上传容器的样式。(自己可以详读读 element-ui 中的相关文档,配置相应的参数) 3. on-success 是上传图片成功后绑定的一个函数。函数如下:
handleAvatarSuccess(res){//res这个参数自己打印出来一看便知,在此不做解释 console.log(res);//将后端发送的地址赋值到我们需要显示的img中的src动态绑定的参数中this.imageUrl = res.data.path;//将图片地址绑定到我们的form表单数据中 后期存入数据库中 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”},//这里我写在了vue组件里边的data中,动态绑定了。 至此,前端的所有配置已完毕。接下来重要的部分来了,后端接收前端的传输的图片,发送给前端访问地址。
2.2 、后端我使用的是 node.js 来接收并处理图片文件信息。
在服务端我用到了 express 用来创建服务,使用 multer 插件处理上传文件,他的效率是非常高的,官方文档地址(https://www.npmjs.com/package/multer)
- 安装 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"))// 解析post请求数据app.use(express.urlencoded({ extended:true}))app.use(express.json())// 链接数据库require("./module/mongoose/mongoose")//引入sessionapp.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();// 引入multerconst multer =require("multer")// 上传图片的方法const storage = multer.diskStorage({// 存储位置 destination:function(req, file, callback){// 参数解释 param1:错误信息 param2:上传图片的服务端保存路径,注意这里的路径写法callback(null,"./public/vue_img/blogImg")},// 确定文件名,在这儿采用了时间戳和图片文件原名为上传的图片文件命名,可以保证名字不重复filename:function(req, file, cb){cb(null,`${Date.now()}-${file.originalname}`)}})// 得到multer对象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、效果展示
- 前端界面成功请求服务端的图片并显示
- 服务端已经在相应目录下增加了此图片。 如果有不对的地方欢迎大佬在讨论区留言交流。
版权归原作者 初入编域 所有, 如有侵权,请联系我们删除。