注:
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>