vue+element上传图片
一、html页面上传图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<input type="file" id="fileInput" />
<img id="imagePreview" src="" alt="Image Preview" />
</div>
</body>
</html>
<script>
const fileInput = document.getElementById('fileInput');
const imagePreview = document.getElementById('imagePreview');
fileInput.addEventListener('change', (event) => {
// 获取用户选择的第一个文件
const file = event.target.files[0];
if (file) {
const objectURL = URL.createObjectURL(file); // 创建临时 URL
imagePreview.src = objectURL; // 设置为 img 标签的 src
}
});
</script>
二、vue选择图片和上传图片
1.:auto-upload="false"取消自动上传,点击上传头像按钮上传
2.:on-change文件上传成功时的钩子,(选择图片后,把图片格式转换为base64格式)
3.点击button按钮和upload组件都可以选择图片
4.上传图片(发送请求更新头像,userStore重新更新数据,给用户提示)
<template>
<PageContainer title="更换头像">
<el-upload
ref="uploadRef"
class="avatar-uploader"
:auto-upload="false"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
:on-change="onSelectFile"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<div class="btns">
<el-button icon="Plus" type="primary" @click="onSelectFn"
>选择图片</el-button
>
<el-button icon="Upload" type="success" @click="onUpdateFn"
>上传头像</el-button
>
</div>
</PageContainer>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { Plus, Upload } from "@element-plus/icons-vue";
import PageContainer from "@/components/PageContainer.vue";
import { updateAvatarApi } from "@/api/user";
import { useUserStore } from "@/store";
//基于store的数据拿到imageUrl的初始值
const userStore = useUserStore();
//图片上传
const imageUrl = ref(userStore.userInfo.user_pic);
const uploadRef = ref();
const beforeAvatarUpload = (rawFile) => {
if (rawFile.type !== "image/jpeg") {
ElMessage.error("Avatar picture must be JPG format!");
return false;
} else if (rawFile.size / 1024 / 1024 > 2) {
ElMessage.error("Avatar picture size can not exceed 2MB!");
return false;
}
return true;
};
const onSelectFile = (uploadFile) => {
//基于fileReader读取图片做预览
const reader = new FileReader();
// 将文件读入为Data URL
reader.readAsDataURL(uploadFile.raw);
// 获取Base64字符串
reader.onload = () => {
imageUrl.value = reader.result;
};
};
const onSelectFn = () => {
uploadRef.value.$el.querySelector("input").click();
};
const onUpdateFn = async () => {
//发送请求更新头像
await updateAvatarApi(imageUrl.value);
//userStore重新渲染
await userStore.getuserInfo();
//提示用户
ElMessage.success("修改成功");
};
</script>
<style lang="scss">
.avatar-uploader .avatar {
width: 178px;
height: 178px;
display: block;
}
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.btns {
margin-top: 20px;
}
</style>
三、表单中上传图片
1.在表单中使用upload组件
2.URL.createObjectURL
是一个在 JavaScript 中用于创建一个指向 Blob
或 File
对象的临时 URL 的方法。这种方法非常有用,尤其是在处理文件上传或生成动态内容时,比如图像预览。imageUrl.value = URL.createObjectURL(uploadFile.raw);
-
生成临时 URL: 它为
Blob
或File
对象生成一个可以在浏览器中使用的 URL。这个 URL 是临时的,仅在页面生命周期内有效。 -
文件预览: 在用户选择文件后,可以使用这个 URL 显示图像预览。比如,当用户上传一张图片时,可以生成这个 URL 并将其设置为
<img>
标签的src
属性。
3.使用 Axios 来获取网络图片并将其转换为 File 对象。以下是具体的实现步骤:
- 使用 Axios 请求获取图片的 Blob 数据。
- 将 Blob 数据转换为 File 对象。
<template>
<el-drawer v-model="drawerVisible" direction="rtl">
<template #header>
<h4>{{ formModel.id ? "编辑文章" : "添加文章" }}</h4>
</template>
<template #default>
<el-form :model="formModel" :rules="rules" ref="formRef">
<el-form-item label="文章标题" prop="title">
<el-input v-model="formModel.title"></el-input>
</el-form-item>
<el-form-item label="文章分类" props="cate_id">
<ChannelSelect
v-model:modelValue="formModel.cate_id"
width="100%"
></ChannelSelect>
</el-form-item>
<el-form-item label="文章封面" prop="cover_img">
<el-upload
class="avatar-uploader"
:auto-upload="false"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
:on-change="onSelectFile"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</el-form-item>
<el-form-item label="文章内容" prop="content">
<div class="editor">
<QuillEditor
ref="editorRef"
v-model:content="formModel.content"
theme="snow"
contentType="html"
/>
</div>
</el-form-item>
<el-form-item label=" ">
<div>
<el-button type="primary" @click="onPublisg('已发布')"
>发布</el-button
>
<el-button @click="onPublisg('草稿')">草稿</el-button>
</div>
</el-form-item>
</el-form>
</template>
</el-drawer>
</template>
<script setup>
import { ref, nextTick } from "vue";
import ChannelSelect from "@/view/article/component/ChannelSelect.vue";
import {
addArticlePublishApi,
getArticleInfoApi,
editArticleInfoApi,
} from "@/api/article.js";
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { ElMessage } from "element-plus";
import { baseURL } from "@/utils/request";
const drawerVisible = ref(false);
const emit = defineEmits(["success"]);
const deaultFormModel = {
title: "",
cate_id: "",
cover_img: "",
content: "",
state: "",
};
const formModel = ref({ ...deaultFormModel });
const formRef = ref();
const editorRef = ref();
const open = async (row) => {
drawerVisible.value = true;
if (row.id) {
const res = await getArticleInfoApi(row.id);
formModel.value = res.data.data;
console.log(res);
imageUrl.value = `${baseURL}${res.data.data.cover_img}`;
//提交给后台需要的格式是file格式对象,需要将网络图片地址转为file对象,将 File 对象赋值给表单模型
const file = await convertImageUrlToFile(
imageUrl,
formModel.value.cover_img
);
formModel.value.cover_img = file;
} else {
formModel.value = { ...deaultFormModel };
console.log("editorRef.value", editorRef.value);
imageUrl.value = "";
await nextTick(() => {
editorRef.value.setHTML("");
});
}
};
defineExpose({ open });
//图片上传
const imageUrl = ref("");
const beforeAvatarUpload = (rawFile) => {
if (rawFile.type !== "image/jpeg") {
ElMessage.error("Avatar picture must be JPG format!");
return false;
} else if (rawFile.size / 1024 / 1024 > 2) {
ElMessage.error("Avatar picture size can not exceed 2MB!");
return false;
}
return true;
};
const onSelectFile = (uploadFile) => {
imageUrl.value = URL.createObjectURL(uploadFile.raw);
formModel.value.cover_img = uploadFile.raw;
};
const onPublisg = async (state) => {
formModel.value.state = state;
const fd = new FormData();
for (let key in formModel.value) {
fd.append(key, formModel.value[key]);
}
if (formModel.value.id) {
await editArticleInfoApi(fd);
ElMessage.success("修改成功");
drawerVisible.value = false;
emit("success", "emit");
} else {
await addArticlePublishApi(fd);
ElMessage.success("添加成功");
drawerVisible.value = false;
console.log("drawerVisible.value", drawerVisible.value);
emit("success", "add");
}
};
const convertImageUrlToFile = async (imageUrl, fileName = "image.jpg") => {
// 使用 Axios 获取图片
const response = await axios.get(imageUrl, {
responseType: "blob", // 设置响应类型为 blob
});
// 创建 File 对象
const file = new File([response.data], fileName, {
type: response.data.type,
});
return file;
};
</script>
<style lang="scss" scoped>
.avatar-uploader .avatar {
width: 178px;
height: 178px;
display: block;
}
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.editor {
width: 100%;
.ql-editor {
min-height: 200px !important;
}
}
</style>