您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么用Vue組件封裝上傳圖片和視頻”,在日常操作中,相信很多人在怎么用Vue組件封裝上傳圖片和視頻問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么用Vue組件封裝上傳圖片和視頻”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
首先下載依賴:
cnpm i -S vue-uuid ali-oss
圖片和視頻字段都是數(shù)組類型,保證可以上傳多個(gè)文件。
UploadImageVideo:
<!--UploadImageVideo 分片上傳 --> <template> <div class="UploadImageVideo"> <el-upload action :on-change="handleChange" :on-remove="handleRemove" :limit="limitFileNumber" :on-exceed="handleExceed" :file-list="_fileList" :http-request="handleHttpRequest" :before-upload="handleBeforeUpload" :multiple="isMultiple" > <el-button slot="trigger" size="small" type="primary">選擇文件</el-button> <div slot="tip" class="el-upload__tip">{{ tip }}</div> </el-upload> <el-dialog title="上傳進(jìn)度" :visible.sync="dialogTableVisible" :close-on-click-modal="false" :modal-append-to-body="false" > <el-progress :text-inside="true" :stroke-width="26" :percentage="percentage"></el-progress> </el-dialog> </div> </template> <script> import { uuid } from "vue-uuid"; const OSS = require("ali-oss"); export default { name: "", components: {}, props: { region: { type: String, default: "oss-cn-chengdu" }, accessKeyId: { type: String, default: "xxx" }, accessKeySecret: { type: String, default: "xxx" }, //存儲(chǔ)位置 bucket: { type: String, required: true }, currentUrls: { type: Array, default: () => [], required: true }, //限制上傳文件數(shù)量 limitFileNumber: { type: Number, default: 1 }, //是否支持多選 isMultiple: { type: Boolean, default: false }, //文件格式 fileType: { type: String, default: "" }, //提示 tip: { type: String } }, data() { return { client: new OSS({ region: this.region, accessKeyId: this.accessKeyId, accessKeySecret: this.accessKeySecret, bucket: this.bucket }), percentage: 0, dialogTableVisible: false, fileList: [] }; }, computed: { //注意:計(jì)算屬性里面慎用console.log()來(lái)打印,因?yàn)橛锌赡艽蛴〉淖兞渴且蕾嚹硞€(gè)屬性而出現(xiàn)該計(jì)算屬性重復(fù)調(diào)用?。。。。?! _fileList() { const arr = []; //一定要this.currentUrls判斷一下是否非空,否則要報(bào)錯(cuò) if (this.currentUrls.length !== 0) { for (const item of this.currentUrls) { let { pathname } = new URL(item); arr.push({ name: decodeURIComponent(pathname), url: item }); } } this.fileList = arr; //這行代碼很重要??! return arr; } }, created() {}, mounted() {}, methods: { handleChange(file, fileList) { this.fileList = fileList; }, handleRemove(file, fileList) { this.fileList = fileList; }, handleExceed(files, fileList) { this.$message.warning( `當(dāng)前限制選擇 ${this.limitFileNumber} 個(gè)文件,本次選擇了 ${ files.length } 個(gè)文件,共選擇了 ${files.length + fileList.length} 個(gè)文件` ); }, //注意:為了讓自定義上傳handleHttpRequest生效,需滿足: // 1、設(shè)置:auto-upload='true'或者不寫這個(gè)屬性,因?yàn)樗J(rèn)為true 2、設(shè)置action='#'或者直接寫action handleHttpRequest(file) { //雖然沒有內(nèi)容,但是這個(gè)函數(shù)不能少! }, //注意:自定義上傳handleHttpRequest必須要生效,才會(huì)觸發(fā)before-upload鉤子函數(shù) handleBeforeUpload(file) { if (this.fileType == "image") { let { type, size, name } = file; let isJPEG = type === "image/jpeg"; let isJPG = type === "image/jpg"; let isPNG = type === "image/png"; let isLt5M = size / 1024 / 1024 < 5; if (!isJPEG && !isJPG && !isPNG) { this.$message.error("上傳圖片只能是 JPEG/JPG/PNG 格式!"); return false; } if (!isLt5M) { this.$message.error("單張圖片大小不能超過(guò) 5MB!"); return false; } } if (this.fileType == "video") { let { type, size, name } = file; let isMP4 = type === "video/mp4"; let isLt50M = size / 1024 / 1024 < 50; if (!isMP4) { this.$message.error("上傳視頻只能是 MP4 格式!"); return false; } if (!isLt50M) { this.$message.error("單個(gè)視頻大小不能超過(guò) 50MB!"); return false; } } }, // 分片上傳數(shù)據(jù),可展示進(jìn)度條。上傳重命名后的文件到alioss, 并返回單個(gè)文件url字符串。可支持中文文件名 async UploadImageVideo(filename, file) { let newFileName = filename.split(".")[0] + "-" + uuid.v1() + "." + filename.split(".")[1]; let that = this; that.dialogTableVisible = true; let { res: { requestUrls } } = await this.client.multipartUpload(newFileName, file, { progress: function(p, checkpoint) { that.percentage = parseFloat((p * 100).toFixed(2)); } }); if (that.percentage == 100) { that.dialogTableVisible = false; } let { origin, pathname } = new URL(requestUrls[0]); return origin + decodeURIComponent(pathname); }, //批量上傳文件。返回成功上傳的url數(shù)組 async addFiles() { let urls = []; if (this.fileList.length !== 0) { for (const item of this.fileList) { let { name, raw } = item; let pathname = await this.UploadImageVideo(name, raw); urls.push(pathname); } } return urls; }, //更新文件數(shù)據(jù)。上傳新數(shù)據(jù)到服務(wù)器,并刪除服務(wù)器中的舊數(shù)據(jù),返回更新后的url數(shù)組 async UpdateFiles() { let arr_newUploaded = []; //新上傳的圖片url。 let arr_original = []; //原有的圖片url。不用刪除 let arr_delete = []; //需要?jiǎng)h除的圖片url。 if (this.fileList.length !== 0) { for (const { raw, name, url } of this.fileList) { //注意:這里一定要判斷raw是否存在。存在,則表示是新上傳的;不存在,則表示是原有的 if (raw) { let pathname = await this.UploadImageVideo(name, raw); arr_newUploaded.push(pathname); } if (this.currentUrls.includes(url)) { arr_original.push(url); } } } for (const element of this.currentUrls) { if (!arr_original.includes(element)) { arr_delete.push(element); } } await this.deleteMultiFiles(arr_delete); return [...arr_original, ...arr_newUploaded]; }, //批量刪除服務(wù)器中的文件。參數(shù):待刪除到服務(wù)器文件url數(shù)組。 async deleteMultiFiles(urls = []) { let arr_pathname = []; if (urls.length !== 0) { for (const item of urls) { //不要用let url=require("url");url.parse();已失效。要用new URL() let { pathname } = new URL(item); // decodeURIComponent()函數(shù)將中文亂碼轉(zhuǎn)為中文 arr_pathname.push(decodeURIComponent(pathname)); } //刪除服務(wù)器中的圖片 await this.client.deleteMulti(arr_pathname); } } }, watch: {} }; </script> <style lang="scss" scoped> .UploadImageVideo { /*去除upload組件過(guò)渡效果*/ ::v-deep .el-upload-list__item { transition: none !important; } } </style>
使用:
<UploadImageVideo ref="ref_UploadImageVideo" bucket="xxx" :currentUrls="formData.imgurl" :limitFileNumber="3" tip="1、最多上傳3張照片; 2、上傳圖片只能是 JPEG/JPG/PNG 格式; 3、單張圖片大小不能超過(guò) 5MB!" fileType="image" :isMultiple="true" ></UploadImageVideo>
fileType可選。默認(rèn)不寫,表示圖片、視頻都可上傳。fileType="image"表示只能上傳圖片。fileType="video"表示只能上傳視頻
bucket必選。
isMultiple可選。默認(rèn)為false
currentUrls必選。當(dāng)前目前已有的文件服務(wù)器url數(shù)組。通常新增文件時(shí),傳入的currentUrls為空數(shù)組[];更新文件時(shí),傳入到currentUrls為非空數(shù)組
tip可選。提示內(nèi)容
提供的方法:(當(dāng)前組件中所有的上傳都是批量上傳,且為分片上傳,以展示上傳進(jìn)度條)
UpdateFiles()。更新文件數(shù)據(jù)。上傳新數(shù)據(jù)到服務(wù)器,并刪除服務(wù)器中的舊數(shù)據(jù),返回更新后的url數(shù)組
addFiles()。批量上傳文件。返回成功上傳的url數(shù)組
deleteMultiFiles(urls = [])。批量刪除服務(wù)器中的文件。參數(shù):待刪除到服務(wù)器文件url數(shù)組。
UploadImageVideo(filename, file)。分片上傳數(shù)據(jù),可展示進(jìn)度條。上傳重命名后的文件到alioss, 并返回單個(gè)文件url字符串。可支持中文文件名
調(diào)用組件中的方法:例如可通過(guò) let urls = await this.$refs["ref_UploadImageVideo"].addFiles();調(diào)用批量上傳圖片或視頻的方法
例1:
<!--userManage--> <template> <div class="userManage"> <el-card> <div > <el-input v-model="searchName" clearable placeholder="輸入用戶名稱搜索" /> <el-button sizi="mini" type="success" icon="el-icon-search" @click="searchUser(searchName)" >搜索</el-button> <el-button sizi="mini" type="warning" icon="el-icon-refresh-left" @click="searchName = ''" >重置</el-button> <el-button sizi="mini" @click="handleAdd()" type="primary" icon="el-icon-plus">新增</el-button> <el-button @click="getUserList()" sizi="mini" icon="el-icon-refresh" >刷新</el-button> </div> <el-table :data="tableData" border v-loading="isLoading"> <el-table-column label="用戶名" prop="username" align="center" width="150px"></el-table-column> <el-table-column label="密碼" prop="password" align="center"></el-table-column> <el-table-column label="圖片" align="center"> <template slot-scope="scope"> <div style=" display: flex; justify-content: space-around; flex-flow: row wrap; " > <el-image v-for="(item, index) in scope.row.imgurl" :key="index" :src="item" :preview-src-list="scope.row.imgurl" ></el-image> <!-- <a :href="scope.row.imgurl" rel="external nofollow" target="_blank">{{scope.row.imgurl}}</a> --> </div> </template> </el-table-column> <el-table-column label="操作" align="center"> <template slot-scope="scope"> <el-button size="mini" @click="showEditDialog(scope.row)"> <i class="el-icon-edit" /> 編輯 </el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.row)"> <i class="el-icon-delete" /> 刪除 </el-button> </template> </el-table-column> </el-table> </el-card> <UserManageDialog :dialog="dialog" :formData="formData" @addUser="addUser" @editUser="editUser"></UserManageDialog> </div> </template> <script> import UserManageDialog from "./userManageDialog.vue"; import { client_alioss, deleteMultiFiles } from "@/utils/alioss.js"; import { addUser, getUserList, editUser, deleteUser, searchUser } from "@/api/userManage/index"; export default { name: "userManage", components: { UserManageDialog }, data() { return { searchName: "", isLoading: false, dialog: { show: false, title: "" }, formData: {}, tableData: [ { _id: "", username: "admin", password: "123", imgurl: [] } ], currentImgs: [] }; }, props: {}, created() {}, mounted() { this.getUserList(); }, computed: {}, methods: { //獲取用戶列表 async getUserList() { this.isLoading = true; let { data } = await getUserList(); this.tableData = data.data; this.isLoading = false; }, //打開新增用戶窗口 handleAdd() { this.dialog = { show: true, title: "新增用戶", option: "add" }; this.formData = { username: "", password: "", imgurl: [] }; }, //打開編輯用戶窗口 showEditDialog(row) { this.currentImgs = row.imgurl; this.dialog = { show: true, title: "編輯用戶", option: "edit" }; this.formData = { _id: row._id, username: row.username, password: row.password, imgurl: row.imgurl }; }, //新增用戶 async addUser(urls) { this.formData.imgurl = urls; await addUser(this.formData); this.dialog.show = false; this.$notify({ title: "成功", message: "新增用戶成功!", type: "success" }); this.getUserList(); }, //編輯用戶 async editUser(urls) { this.formData.imgurl = urls; await editUser(this.formData, this.formData._id); //更新數(shù)據(jù)庫(kù),尤其是圖片url this.dialog.show = false; this.$notify({ title: "成功", message: "編輯用戶成功!", type: "success" }); this.getUserList(); }, //刪除用戶 handleDelete({ _id }) { this.$confirm("此操作將永久刪除該文件, 是否繼續(xù)?", "提示", { confirmButtonText: "確定", cancelButtonText: "取消", type: "warning" }) .then(async () => { this.$message({ type: "success", message: "刪除成功!", showClose: true }); let { data: { imgurl } } = await deleteUser(_id); //刪除服務(wù)器中的文件。傳入待刪除的url數(shù)組 await deleteMultiFiles(imgurl); this.getUserList(); }) .catch(() => { this.$message({ type: "info", message: "已取消刪除", showClose: true }); }); }, //根據(jù)用戶名查詢 async searchUser(searchName) { this.isLoading = true; let { data } = await searchUser({ searchName }); this.tableData = data.data; this.isLoading = false; } }, watch: {} }; </script> <style lang="scss" scoped> .userManage { } </style>
<!--userManageDialog --> <template> <div class="userManageDialog"> <el-dialog :title="dialog.title" width="45%" :visible.sync="dialog.show" v-if="dialog.show"> <el-form ref="ref_form_userManage" :model="formData" :rules="rules" label-width="100px"> <el-form-item label="用戶名" prop="username"> <el-input v-model="formData.username" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="密碼" prop="password"> <el-input v-model="formData.password" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="圖片" prop="imgurl"> <!-- fileType屬性不寫的話,表示圖片、視頻都可上傳。fileType="image"表示只能上傳圖片。fileType="video"表示只能上傳視頻 --> <UploadImageVideo ref="ref_UploadImageVideo" bucket="bucket-lijiang-test" :currentUrls="formData.imgurl" :limitFileNumber="3" tip="1、最多上傳3張照片; 2、上傳圖片只能是 JPEG/JPG/PNG 格式; 3、單張圖片大小不能超過(guò) 5MB!" fileType="image" :isMultiple="true" ></UploadImageVideo> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialog.show = false">取 消</el-button> <el-button v-if="dialog.option == 'add'" @click="addUser('ref_form_userManage')" type="primary" >確 定</el-button> <el-button v-if="dialog.option == 'edit'" @click="editUser('ref_form_userManage')" type="primary" >確 定</el-button> </div> </el-dialog> </div> </template> <script> import UploadImageVideo from "@/components/UploadImageVideo"; export default { name: "userManageDialog", components: { UploadImageVideo }, props: ["dialog", "formData"], data() { return { fileList: [], rules: { username: [ { required: true, message: "請(qǐng)輸入用戶名稱", trigger: "blur" } ] } }; }, created() {}, mounted() {}, computed: {}, methods: { addUser(formName) { this.$refs[formName].validate(async valid => { if (valid) { let urls = await this.$refs["ref_UploadImageVideo"].addFiles(); this.$emit("addUser", urls); } else { console.log("error submit!!"); return false; } }); }, editUser(formName) { this.$refs[formName].validate(async valid => { if (valid) { let urls = await this.$refs["ref_UploadImageVideo"].UpdateFiles(); this.$emit("editUser", urls); } else { console.log("error submit!!"); return false; } }); } }, watch: {} }; </script> <style lang="scss" scoped> </style>
import { uuid } from 'vue-uuid'; const OSS = require("ali-oss"); let client = new OSS({ region: "oss-cn-chengdu", accessKeyId: "LTAI5tQPHvixV8aakp1vg8Jr", accessKeySecret: "xYyToToPe8UFQMdt4hpTUS4PNxzl9S", bucket: "bucket-lijiang-test", }); export const client_alioss = client; //刪除文件數(shù)組 export async function deleteMultiFiles(urls = []) { let arr_pathname = []; if (urls.length !== 0) { for (const item of urls) { //不要用let url=require("url");url.parse();已失效。要用new URL() let { pathname } = new URL(item); // decodeURIComponent()函數(shù)將中文亂碼轉(zhuǎn)為中文 arr_pathname.push(decodeURIComponent(pathname)); } await client.deleteMulti(arr_pathname); } }
import request from '@/utils/request' // 獲取用戶列表 export function getUserList() { return request({ url: '/api/userManage', method: 'get' }) } // 新增用戶 export function addUser(data) { return request({ url: '/api/userManage', method: 'post', data }) } // 編輯用戶 export function editUser(data, _id) { return request({ url: `/api/userManage/${_id}`, method: 'put', data }) } // 刪除用戶 export function deleteUser(_id) { return request({ url: `/api/userManage/${_id}`, method: 'delete' }) } // 根據(jù)關(guān)鍵字查詢 export function searchUser(data) { return request({ url: `/api/userManage/search`, method: 'get', params: data }) }
const router = require('koa-router')() const User = require("../models/User"); //引入模塊模型 router.prefix('/userManage') //獲取用戶列表 router.get('/', async (ctx, next) => { let data = await User.find({}) ctx.body = { code: 200, message: "請(qǐng)求成功", data, } }) //新增用戶 router.post('/', async (ctx, next) => { let { username, password, imgurl } = ctx.request.body; await User.create({ username, password, imgurl }) ctx.body = { code: 200, message: "新增成功" } }) //編輯用戶 router.put('/:_id', async (ctx, next) => { let { username, password, imgurl } = ctx.request.body; let { _id } = ctx.params await User.findByIdAndUpdate(_id, { username, password, imgurl }) ctx.body = { code: 200, message: "編輯成功" } }) //刪除用戶 router.delete('/:_id', async (ctx, next) => { let { _id } = ctx.params; let { imgurl } = await User.findByIdAndDelete(_id) ctx.body = { code: 200, message: "刪除成功", imgurl } }) //根據(jù)關(guān)鍵字查詢用戶。模糊查詢 router.get('/search', async (ctx, next) => { let { searchName } = ctx.request.query; let data = await User.find({ username: { $regex: searchName } }) ctx.body = { code: 200, message: "查詢成功", data } }) module.exports = router
到此,關(guān)于“怎么用Vue組件封裝上傳圖片和視頻”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。