vue3加axios配合element-plus实现图片等文件本地上传,并获取服务器返回的真实地址数据,前端写法

小白写法嘿嘿

开发工具和关键词

开发工具: vscode

关键词:vue3、element-plus、axios

后端

后端业务逻辑处理使用的是unicloud的云函数,大家可以看我上一篇文章。

思路

1、禁止element-plus的el-upload组件自动上传,变成手动上传,提交表单时候统一处理上传文件

2、此时el-upload组件中的file文件保存到了v-model:file-list="fileList"的fileList的变量中,数据类型类型是file对象的数组

3、提交表单,循环fileList数组,将file数据类型的文件转化成base64编码

4、将子元素为base64编码数据的图片数组依次上传到服务器,并依次获取一个真实的服务器图片地址,并将这些真实地址保存到pictureslist数组

4、后面可以根据自己的代码逻辑处理真实地址的图片数组pictureslist,如:商品多张图片可以将数组转为json格式,保存到数据表中的某一个pictures字段中,后续展示商品直接读取即可

注意:这里不考虑文件上传中断和大文件的情况。

完整代码

addproduct.vue

html 复制代码
<template>
    <div style="width: 80%;">
        <el-form :model="form" label-width="auto" style="max-width: 600px">
            <el-form-item label="标题">
                <el-input v-model="form.bt" />
            </el-form-item>
            <el-upload v-model:file-list="fileList" action="ok" :auto-upload="false" list-type="picture-card"
                :on-preview="handlePictureCardPreview" :on-remove="handleRemove" multiple>
                <el-icon>
                    添加
                    <Plus />
                </el-icon>
            </el-upload>

            <el-dialog v-model="dialogVisible">
                <img w-full :src="dialogImageUrl" alt="Preview Image" />
            </el-dialog>
            <el-form-item>
                <el-button type="primary" @click="onSubmit">新增</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
import { ref, reactive } from 'vue'
import axios from 'axios'


const dialogImageUrl = ref('')
const dialogVisible = ref(false)

//这里用了响应式数据
var form = reactive({
    bt: '',
//tp是保存了真实图片地址后的json数组
    tp: '',
})

export default {
    name: 'HomeView',
    data() {
        return {
            form,
            dialogImageUrl,
            dialogVisible,
            fileList: [],
            zh: sessionStorage.getItem('zh')
        }
    },
    methods: {
        async onSubmit() {
            var that = this

            console.log('submit!')
            console.log(this.form);
            if (this.fileList.length == 0) {
                return ElMessage({
                    message: '请先上传图片!',
                    grouping: true,
                    type: 'warning',
                });
            }
            await this.upaction(); // 等待上传图片完成
            console.log("我的上传图片的真实路径", this.fileList);
            var pictureslist = []


            for (let i = 0; i < this.fileList.length; i++) {
                pictureslist.push(this.fileList[i].url)
             
            }

            // 将合并后的数组转换为 JSON 字符串
            var jsonString = JSON.stringify(pictureslist);

            console.log("转换后的 JSON 字符串", jsonString);

            // 将转换后的 JSON 字符串赋值给 this.form.tp
            this.form.tp = jsonString;
            console.log("待上传表单数据", form);
            this.form.zh = this.zh

            // 将表单数据上传服务器
            const res = await axios.post(
                "/api/addproduct", // 请求后端的 URL
                that.form,
                {
                    headers: {
                        "Content-Type": "application/json;charset=utf-8",
                        "Access-Control-Allow-Origin": "*", // 允许所有域名访问,或者设置为特定的域名
                        "Access-Control-Allow-Methods": "GET, POST, OPTIONS", // 允许的请求方法
                        "Access-Control-Allow-Headers": "Content-Type", // 允许的请求头
                    },
                }
            );
            console.log("请求后", res);
            loadingInstance.close()
            ElMessage({
                message: '上传成功!',
                grouping: true,
                type: 'success',
            })

        },
        handlePictureCardPreview(uploadFile) {
            console.log(uploadFile);
            this.dialogImageUrl = uploadFile.url
            this.dialogVisible = true
        },

        handleRemove(file, fileList) {
            console.log(file)
            console.log(fileList)
        },

        // 依次上传图片
        async upaction() {
            var that = this
            for (let i = 0; i < this.fileList.length; i++) {
                var src = await this.uploadFile(this.fileList[i]);
                this.fileList[i].url = src
            }
        },

//保存至服务器后返回真实图片路径地址
        async uploadFile(file) {
            console.log("uploadFile中,未编码url为", file.url);
            const newbasesrc = await this.getdata(file);
            console.log("编码url后", newbasesrc);
            const res = await axios.post(
                "/api/upload", // 请求后端的 URL
                { file: newbasesrc },
                {
                    headers: {
                        "Content-Type": "multipart/form-data;charset=utf-8",
                        "Access-Control-Allow-Origin": "*", // 允许所有域名访问,或者设置为特定的域名
                        "Access-Control-Allow-Methods": "GET, POST, OPTIONS", // 允许的请求方法
                        "Access-Control-Allow-Headers": "Content-Type", // 允许的请求头
                    },
                }
            );
            console.log(res);
            return res.data.fileUrl;
        },

//以下两个自定义函数是为了将input直接获取的file对象转成base64编码格式

        async getdata(file) {
            // 使用 FileReader 将文件转换为 base64 编码字符串
            console.log("getdata函数中,准备转化", file);
            const base64String = await this.readFileAsBase64(file);
            console.log("获得编码", base64String);
            return base64String;
        },

        readFileAsBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = (event) => {
                    // 将文件转换为 base64 编码
                    const base64String = event.target.result;
                    resolve(base64String);
                };
                reader.onerror = reject;
                // 读取文件内容并转换为 base64 编码字符串
                reader.readAsDataURL(file.raw);
            });
        },
    }
}
</script>

如果对您有所帮助,给个小赞赞吧!🌹

相关推荐
大杯咖啡5 小时前
localStorage与sessionStorage的区别
前端·javascript
RaidenLiu5 小时前
告别陷阱:精通Flutter Signals的生命周期、高级API与调试之道
前端·flutter·前端框架
非凡ghost5 小时前
HWiNFO(专业系统信息检测工具)
前端·javascript·后端
非凡ghost5 小时前
FireAlpaca(免费数字绘图软件)
前端·javascript·后端
非凡ghost5 小时前
Sucrose Wallpaper Engine(动态壁纸管理工具)
前端·javascript·后端
拉不动的猪5 小时前
为什么不建议项目里用延时器作为规定时间内的业务操作
前端·javascript·vue.js
该用户已不存在5 小时前
Gemini CLI 扩展,把Nano Banana 搬到终端
前端·后端·ai编程
地方地方5 小时前
前端踩坑记:解决图片与 Div 换行间隙的隐藏元凶
前端·javascript
炒米23335 小时前
【Array】数组的方法
javascript
jason_yang5 小时前
vue3+element-plus按需自动导入-正确姿势
vue.js·vite·element