前端如何用form-data方式上传图片js
PC端和Mob端最多可以上传3张照片 每张大小不超过3M 格式支持bmp,gif,jpg,png,jpeg PC端上传的图片会展示在添加图片按钮和上传图片文案描述中间 mob端默认是一个添加图片的图 如果上传了图片 会出现在添加图片这张图之前 上传到第三张的时候 添加图片这张图就隐藏掉了 当前行显示3张正方形的上传图。这里写的有点多哈 大家可以不看这块 只看js业务逻辑部分 这里思路上面已经写出来
1.场景
工作场景中,需要一个上传图片的功能 效果如下
PC端

mob端

2.业务逻辑
PC端和Mob端最多可以上传3张照片 每张大小不超过3M 格式支持bmp,gif,jpg,png,jpeg PC端上传的图片会展示在添加图片按钮和上传图片文案描述中间 mob端默认是一个添加图片的图 如果上传了图片 会出现在添加图片这张图之前 上传到第三张的时候 添加图片这张图就隐藏掉了 当前行显示3张正方形的上传图。 PC和Mob端每一个上传好的图上面都有一个x按钮 点击x可以删除掉上传的图片 并且这个块是封装成了组件 组件复用在了查看详情页 如果是查看详情 进入这个组件 我这里会传递进来一个resonDisabled 让input框隐藏掉 只能查看当前内容 不能点击上传 代码里的:class="{ 'component-order-return-detail__apply-about-hidden': resonDisabled }"就是控制input隐藏的
3.前后端约定
form-data方式上传 key value格式 上传 这里的baseUrl就是接口的请求地址公共url 做了全局配置而已 可以忽略 这个截图主要看传参格式

4.css部分代码
css实现中 先写了个父元素 包含input和上面的上传图片按钮 父元素 position:relative;子元素 position:absolute;input大小和上面的添加图片按钮大小一致 然后设置了opacity: 0;并且input的z-index层级设置的高一点 透明的浮在按钮之上
layout-mobile-only 是手机端的样式适配
layout-desktop 是PC端的样式适配
layout-responsive 是手机端和PC端分别是什么样式
如果需要写单端 可以手动把这些代码分离出来
这里写的有点多哈 大家可以不看这块 只看js业务逻辑部分 这里思路上面已经写出来了 业务逻辑也不一定一致 大家按照思路自己写就好
<!-- 上传图片按钮相关代码 -->
<div class="component-order-return-detail__apply-about-outer">
<div class="component-order-return-detail__apply-about-reason">图片信息</div>
<div class="component-order-return-detail__apply-about-position layout-desktop-only">
<div class="component-order-return-detail__apply-about-upload">+ 添加图片</div>
<input class="component-order-return-detail__apply-about-file component-order-return-detail__apply-about-upload" :class="{ 'component-order-return-detail__apply-about-hidden': resonDisabled }" type="file" multiple accept="image/png,image/jpeg,image/jpg,image/gif,image/bmp" @change="uploadApplyImage" />
</div>
</div>
<!-- PC端展示上传的图相关代码 以及mob端展示默认上传按钮以及上传图片以后 不够3张 默认图片往后推移相关逻辑 -->
<div v-if="showUploadImage" class="component-order-return-detail__apply-about-static">
<div v-for="(item, index) of returnImageInfo" :key="index" class="component-order-return-detail__apply-about-static-outer">
<img class="component-order-return-detail__apply-about-img" :src="item.url" alt="" />
<svg-icon name="icon-delete-img" class="component-order-return-detail__delete-svg" @click="deleteImage"></svg-icon>
</div>
<img v-if="returnImageInfo.length < 3" class="component-order-return-detail__apply-about-img" :src="addMobileImage" alt="" />
</div>
<style lang="scss">
$MQMobile: 1024px !default;
@mixin layout-mobile-only {
@media (max-width: calc(#{$MQMobile - 1px})) {
@content;
}
}
@mixin layout-desktop {
@media (min-width: $MQMobile) {
@content;
}
}
// RESPONSIVE
@mixin layout-responsive($property, $mobile: null, $desktop: null, $lage-desktop: null) {
@if ($mobile) {
@include layout-mobile {
#{$property}: $mobile;
}
}
@if ($desktop) {
@include layout-desktop {
#{$property}: $desktop;
}
}
}
.component-order-return-detail__apply-about-outer {
width: 100%;
@include layout-desktop {
display: flex;
align-items: center;
}
.block-input {
@include layout-mobile-only {
background-color: transparent !important;
}
}
@include layout-responsive(margin-top, vw(24), 26px);
.component-order-return-detail__apply-about-reason {
@include layout-responsive(width, 100%, 100px);
@include layout-mobile-only {
margin-bottom: vw(6);
}
@include layout-desktop {
margin-right: 49px;
}
}
.component-order-return-detail__reason-red {
color: red;
}
.component-order-return-detail__apply-about-input {
color: #888;
@include layout-responsive(font-size, vw(13), 13px);
@include layout-responsive(width, 100%, 335px);
@include layout-responsive(height, vw(36), 36px);
.block-input {
color: #888;
}
.is-black {
border-color: #c0c0c0 !important;
}
}
.component-order-return-detail__apply-about-textarea {
box-sizing: border-box;
color: #888;
@include layout-responsive(width, 100%, 642px);
@include layout-responsive(height, vw(100), 117px);
@include layout-responsive(line-height, vw(20), 20px);
@include layout-responsive(padding, vw(9) vw(5), 8px 11px);
}
.component-order-return-detail__apply-about-position {
position: relative;
width: 335px;
height: 36px;
.component-order-return-detail__apply-about-hidden {
display: none !important;
}
.component-order-return-detail__apply-about-file {
position: absolute;
z-index: 9;
opacity: 0;
}
.component-order-return-detail__apply-about-upload {
@include layout-desktop {
position: absolute;
width: 335px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
color: #888;
font-size: 13px;
border: 1px solid #c0c0c0;
}
}
}
}
</style>
样式基本上就写好了
5.js部分代码
下面是js部分逻辑 看起来内容有点多 但是注释的很详细 可以耐心看一下 按需贴到自己代码中直接使用 这里的axios是我单独自己写进去的 原项目中 是有封装的 避免看起来麻烦 改写了 如果不小心有问题 大家改一下哈
// 上传图片 点击input的时候 获取到图片信息
uploadApplyImage(e) {
const files = e.target.files
// 如果获取到了上传的内容 才进行以下业务逻辑操作
if (files && files.length > 0) {
// 如果上传多个图片或者文件 对其进行循环 对每个文件的格式都进行校验
for (let i = 0; i < files.length; i++) {
const file = files[i]
// 对支持上传的图片格式 进行判断
if (!/\.(jpg|jpeg|png|bmp|gif|JPG|PNG|BMP|GIF)$/.test(file.name)) {
this.$toast.show('请上传.png /.jpg /.jpeg格式的图片')
} else if (file.size > 1024 * 1024 * 3) {
// 弹出不满足上传格式的弹窗
this.$toast.show('单张图片不可以超过3M,请重新上传')
return
} else {
// 图片超过三张 弹出提示
if (this.returnImageInfo.length === 3) {
this.setToast('最多可上传3张图片')
return
}
console.log('满足上传条件', file)
// 转base64格式 这里约定的格式是key value 直接传file就好 就没用到转base64
// const reader = new FileReader()
// // 因为这两个组件的fils文件不一样所有一个判断
// if (file?.originFileObj) {
// reader.readAsDataURL(file.originFileObj)
// } else {
// reader.readAsDataURL(file)
// }
// reader.addEventListener('load', () => {
// console.log('reader.result', reader.result)
// })
// 转base64格式结束
// 上传图片 form-data方式进行参数序列化 和后端约定的参数是uploadFile
const formData = new FormData()
formData.append('uploadFile', file)
axios.post('/upload', formData,
{headers: { 'Content-Type': 'application/form-data' }})
.then(function (response) {
// 上传成功 执行对应操作
console.log(response);
})
.catch(function (error) {
// 上传失败 执行对应操作
console.log(error);
});
}
}
}
}
好了 就写到这里吧 希望可以对你有帮助~ 如果大家有什么问题 可以私信我 或者我们评论区见
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)