注:
1. 通常狀況不會讓前端直接操做oss(增刪查),但是我遇到了這樣的需求
2. 默認已經開通oss,在oss官網完成了配置
3. 須要使用到element-ui的upload組件html
、前端
accessKeyId
,accessKeySecret
,bucket
bucket
最好區分開發環境和生產環境import axios from 'axios' import OSS from 'ali-oss' import UUID4 from 'uuid/v4' // 下載oss指定地址 export function downloadURL(url) { let link = document.createElement('a'); link.style.display = 'none'; link.href = url; document.body.appendChild(link); link.click(); document.body.removeChild(link); } // 上傳oss export function ossUpload(picForProject, fileBuffer) { let bucketName = ''; // 判斷環境 生產環境而且不爲測試狀態 process.env.NODE_ENV === 'production' ? bucketName = '填你本身申請的' : bucketName = '填你本身申請的'; let client = new OSS({ region: 'oss-cn-beijing', secure: true, // https accessKeyId: '填你本身申請的', accessKeySecret: '填你本身申請的', bucket: bucketName }); const fileName = UUID4().toUpperCase().replace(/-/g, '') const suffix = fileBuffer.name.substr(fileBuffer.name.indexOf('.')) const url = `${picForProject}${fileName}${suffix}` async function put() { try { await client.put(url, fileBuffer) // await xxx(url) 在這裏也能夠直接把地址傳給後端 return { 'code': 200, 'url': url } } catch (e) { return e.message } } return put() }; // 獲取oss地址 export function showPrivateOss(picName) { // 這裏和上傳oss的client是同樣的,應該放在store裏面同一管理的,demo這裏寫在這裏了 let bucketName = ''; process.env.NODE_ENV === 'production' ? bucketName = '填你本身申請的' : bucketName = '填你本身申請的'; let client = new OSS({ secure: true, // https accessKeyId: '填你本身申請的', accessKeySecret: '填你本身申請的', bucket: bucketName, endpoint: 'oss-cn-beijing.aliyuncs.com' }); async function getOssAddr() { try { let signUrl = client.signatureUrl(picName, { expires: 1800 }); // expires單位爲秒 return { 'code': 200, 'url': signUrl } } catch (e) { return e.message } } return getOssAddr() }; // 刪除oss export function deletePrivateOss(picName) { let bucketName = ''; process.env.NODE_ENV === 'production' ? bucketName = '填你本身申請的' : bucketName = '填你本身申請的'; let client = new OSS({ secure: true, // https accessKeyId: '填你本身申請的', accessKeySecret: '填你本身申請的', bucket: bucketName, endpoint: 'oss-cn-beijing.aliyuncs.com' }); async function deleteOssAddr() { try { return client.delete(picName); } catch (e) { return e.message } } return deleteOssAddr() };
<template> <div> <el-upload class="avatar-uploader" action="oss地址" :show-file-list="false" :http-request="uploadToOss" :before-upload="beforeAvatarUpload" :disabled="disabled" :accept="accept" :typeName="typeName" > <div v-loading="loading"> <template v-if="haveUrl"> <img :src="imgUrl" class="avatar" /> <span class="show_icon" v-if="!disabled"> <i class="el-icon-view" @click.stop="handleView()" v-if="typeName==='圖片'"></i> <i class="el-icon-download" @click.stop="handleDownload()" v-else></i> <i class="el-icon-delete" @click.stop="handleRemove()"></i> </span> <span class="show_icon" v-else> <i class="el-icon-view" @click.stop="handleView()" v-if="typeName==='圖片'"></i> <i class="el-icon-download" @click.stop="handleDownload()" v-else></i> </span> </template> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </div> </el-upload> <!--查看圖片--> <el-dialog title="照片詳情" :visible.sync="showBigPic" width="720px" append-to-body> <img :src="imgUrl" width="100%" /> </el-dialog> </div> </template> <script> // 引用工具類(下載指定地址的oss文件、上傳oss、展現oss圖片、刪除指定地址的oss文件) import { downloadURL, ossUpload, showPrivateOss, deletePrivateOss, } from "@/assets/scripts/utils"; // 二次封裝的element的message組件,代碼略 import { errorMsg, successMsg } from "@/components/message"; export default { props: { //對文件的限制 limit: { type: Object, default: function () { return { size: 5, types: ["image/jpeg", "image/png"], }; }, }, // 是否有url haveUrl: { type: Boolean, default: false, }, // 是否禁用 disabled: { type: Boolean, default: false, }, // url的名稱 urlName: { type: String, default: "", }, // 對應的後端字段名,同一頁面可能有多個須要上傳oss的 name: { type: String, default: "", }, // 上傳彈窗,過濾文件類型 accept: { type: String, default: "image/*", }, // 上傳文件類型(文件大小過大提示語也會用到) typeName: { type: String, default: "圖片", }, }, data() { return { showBigPic: false, // 預覽圖片 imgUrl: null, // 圖片地址 ossFileName: "", // oss文件名 loading: false, // 是否上傳中 }; }, watch: { urlName: { handler(newValue, oldValue) { if (newValue) { if (this.typeName !== "圖片" && this.haveUrl) { this.imgUrl = require("@/assets/images/uploaded.jpg"); } else { showPrivateOss(newValue).then((res) => { if (res && res.code) { this.imgUrl = res.url; } else { errorMsg(res); } }); } } }, immediate: true, }, }, methods: { handleView() { this.showBigPic = true; }, handleDownload() { showPrivateOss(this.urlName).then((res) => { if (res && res.code) { downloadURL(res.url); } else { errorMsg(res); } }); }, handleRemove() { let _this = this; deletePrivateOss(this.urlName).then((res) => { if (res.res.status === 204) { successMsg(); // ossDone參數:url文件地址, haveUrl是否有地址, name字段名 this.$emit("callback", null, false, _this.name); } else { errorMsg(res); } }); }, // 上傳oss uploadToOss(elUpload) { this.loading = true; let _this = this; ossUpload("back-image/" + this.ossFileName, elUpload.file).then((res) => { if (res && res.code) { // ossDone參數:url文件地址, haveUrl是否有地址, name字段名 this.$emit("callback", res.url, true, _this.name); } else { errorMsg(res); } this.loading = false; }); }, // 圖片上傳前 驗證圖片大小 beforeAvatarUpload(file) { let isSize = false; if (this.limit.sizeType === "kb") { isSize = file.size / 1024 < this.limit.size; } else { isSize = file.size / 1024 / 1024 < this.limit.size; } if (!isSize) { errorMsg( `${this.typeName}大小不能超過${this.limit.size}${ this.limit.sizeType ? this.limit.sizeType : "MB" }!` ); } return isSize; }, }, }; </script> <style lang="less" scoped> .show_icon { display: inline-block; position: absolute; top: 0; right: 0; width: 108px; height: 72px; i { display: none; } &:hover { background-color: rgba(0, 0, 0, 0.5); i { display: inline; line-height: 72px; color: #fff; font-size: 20px; &:not(:last-child) { margin-right: 10px; } } } } </style>
/* **這是一個彈窗組件,爲了代碼簡潔,刪除了其餘表單內容 **父組件傳來id,即斷定是查看/編輯,須要請求後端詳情 **:before-close須要帶參數,重要!! */ <template> <el-dialog @open="setData" :visible.sync="params.show" :before-close="() => cancel(false)" :close-on-click-modal="false" width="1100px" append-to-body > <div slot="title"> {{params.title}} <span class="title_required"> <span>*</span>爲必填項 </span> </div> <el-form :model="addForm" :inline="true" ref="addForm" label-position="left" label-width="125px" > // 其餘item略 <el-form-item label="營業執照照片" prop="businessLicenseUrl" :rules="[{required: true,message: '不能爲空'}]" > <oss @callback="ossDone" :haveUrl="haveUrl_businessLicenseUrl" :disabled="isDisabled" :urlName="addForm.businessLicenseUrl" name="businessLicenseUrl" /> </el-form-item> <el-form-item label="附件"> <oss @callback="ossDone" :limit="limit" :haveUrl="haveUrl_attachment" :urlName="addForm.attachment" :disabled="isDisabled" accept=".zip, .rar" name="attachment" typeName="壓縮包" /> </el-form-item> </el-form> <span slot="footer"> <el-button @click="cancel(false)" class="cancelBtn">取 消</el-button> <el-button @click="submit" type="primary" class="confirmBtn" v-if="this.params.title !=='查看'" >確 定</el-button> </span> </el-dialog> </template> <script> import oss from "@/components/oss"; import { methodPost } from "@/api"; // 新增/修改用【代碼略】 import { GET_DETAILS } from "@/api/company"; //詳情【代碼略】 import { errorMsg, successMsg } from "@/components/message"; // 二次封裝的message【代碼略】 export default { components: { oss }, data() { return { // 是否有執照 haveUrl_businessLicenseUrl: false, // 是否有附件 haveUrl_attachment: false, // 編輯時,附件的返回值(做爲flag) flag_attachment: null, // 編輯時,執照的返回值(做爲flag) flag_businessLicenseUrl: null, // 附件的大小 limit: { size: 10 } }; }, methods: { // 操做oss後的$emit ossDone(url, haveUrl, name) { this.$set(this.addForm, `${name}`, url); this.$set(this, `haveUrl_${name}`, haveUrl); }, // 彈窗初始化 setData() { this.addForm = {}; this.isDisabled = false; if (this.params.title !== "新增") { this.haveUrl_businessLicenseUrl = true; this.getDetails({ id: this.params.id }); } else { this.haveUrl_attachment = false; this.haveUrl_businessLicenseUrl = false; this.flag_attachment = null; this.flag_businessLicenseUrl = null; } }, getDetails(id) { GET_DETAILS(id).then((res) => { if (res.code === 10000) { this.addForm = res.result; this.flag_attachment = res.result.attachment; this.flag_businessLicenseUrl = res.result.businessLicenseUrl; if (res.result.attachment) { this.haveUrl_attachment = true; } else { this.haveUrl_attachment = false; } } if (this.params.title === "查看") { this.isDisabled = true; } }); }, submit() { // 新增/編輯 this.$refs.addForm.validate((valid) => { if (valid) { let url = "/company/"; if (this.params.data) { url += "update"; } else { url += "insert"; } methodPost(url, this.addForm, true).then((res) => { if (res.code === 10000) { successMsg(); this.cancel(true); } }); } else { errorMsg(); } }); }, cancel(refresh) { if (this.params.title !== "新增") { if (!refresh) { if (this.flag_attachment !== this.addForm.attachment) { errorMsg("修改附件後,請點擊‘肯定’按鈕"); return; } if ( this.flag_businessLicenseUrl !== this.addForm.businessLicenseUrl ) { errorMsg("修改營業執照後,請點擊‘肯定’按鈕"); return; } } } else { if (this.addForm.businessLicenseUrl || this.addForm.attachment) { errorMsg("點擊‘肯定’提交新增內容,或刪除已上傳文件"); return; } } this.$refs.addForm.resetFields(); this.$emit("callback", refresh); // 通知父組件刷新list頁,按實際取捨,父組件代碼略 }, }, }; </script>