赞
踩
微信小程序直传实践
使用的是uview的u-upload组件
1、表单页面
a、页面
<u-upload :fileList="fileList" name="1" multiple :maxCount="3" @delete="deleteFun" @afterRead="afterRead"
:previewFullImage="true"></u-upload>
b、主要js
async afterRead(event) { let fileArr = event.file; let fileList = this.fileList.concat(event.file); this.fileList = fileList; //显示在页面上的图片列表 for (let i = 0; i < fileArr.length; i++) { let data = await initClient(); //获取需要的上传的参数,文件在后面 const host = 'http://阿里后台配置的桶名.oss-cn-shenzhen.aliyuncs.com'; const signature = data.signature; const ossAccessKeyId = data.OSSAccessKeyId; const policy = data.policy; const securityToken = data.securityToken; let tempFile = fileArr[i]; let filePath =tempFile.url; let date = new Date(); let year = date.getFullYear(); let month = date.getMonth() + 1; let month2 = month < 10 ? "0" + month : month; let date2 = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); let name = ""; if (!tempFile.name) { let path = tempFile.url; let indexOf = path.lastIndexOf("/"); name = path.substring(indexOf + 1); } else { name = tempFile.name; } let indexOf = name.lastIndexOf("."); let extension = name.substring(indexOf + 1); const key = `public/car/${tenantId}/${year}/${month2}/${date2}/${uuidv4()}.${extension}`; //const key = '/public/car/000000/2023/01/12/'+res.tempFiles[0].name; //多了一根斜杠报错:InvalidObjectName uni.uploadFile({ url: host, // 开发者服务器的URL。 filePath: filePath, // 待上传文件的文件路径。 name: 'file', // 必须填file。 formData: { key,//传到服务器的地址,切记千万不要有斜杠 policy, 'success_action_status': '200', //让服务端返回200,不然,默认会返回204 OSSAccessKeyId: ossAccessKeyId, signature, 'x-oss-security-token': securityToken // 使用STS签名时必传。 }, success: (res2) => { if (res2.statusCode === 200) { let link = host + "/" + key; //调取后台接口 saveAttachAPI({ link: link, domainUrl: host, name: key, originalName: name, extension: extension, attachSize: tempFile.size }).then(([err, attach_data]) => { if (err) return; let params = { attachId: attach_data, link: link, originalName:name, attachCategory:1, businessType:1 }; this.requestFileList.push(params);//保存需要保存到后台的是数据 }) } }, fail: err => { console.log(err); } }); } } }
ossClient.js
const MpUploadOssHelper = require("./uploadOssHelper.js"); import { getStsAPI } from "@/api/api/my.js" import { getNowTime } from "@/utils/utils.js" export const initClient = async () => { let value = uni.getStorageSync('ossConfig'); //获取缓存里面储存的oss配置数据 //对比时间和缓存里面是否有值,如果过期,需要重新获取sts参数 if (value && value.expiration > getNowTime()) { return value; } else { let [err, data] = await getStsAPI(); const mpHelper = new MpUploadOssHelper({ // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户并授权。 accessKeyId: data.accessKeyId, accessKeySecret: data.accessKeySecret, }); // 生成参数。 const params = mpHelper.createUploadParams(); params.securityToken = data.securityToken; params.expiration = data.expiration; //保存oss配置参数 uni.setStorage({ key: 'ossConfig', data: params, }); return params; } }
uploadOssHelper.js(这个是从oss文档里面copy出来的)
const crypto = require("crypto-js"); class MpUploadOssHelper { constructor(options) { this.accessKeyId = options.accessKeyId; this.accessKeySecret = options.accessKeySecret; // 限制参数的生效时间,单位为小时,默认值为1。 this.timeout = options.timeout || 1; // 限制上传文件的大小,单位为MB,默认值为10。 this.maxSize = options.maxSize || 10; } createUploadParams() { const policy = this.getPolicyBase64(); const signature = this.signature(policy); return { OSSAccessKeyId: this.accessKeyId, policy: policy, signature: signature, }; } getPolicyBase64() { let date = new Date(); // 设置policy过期时间。 date.setHours(date.getHours() + this.timeout); let srcT = date.toISOString(); const policyText = { expiration: srcT, conditions: [ // 限制上传文件大小。 ["content-length-range", 0, this.maxSize * 1024 * 1024], ], }; const buffer = Buffer.from(JSON.stringify(policyText)); return buffer.toString("base64"); } signature(policy) { return crypto.enc.Base64.stringify( crypto.HmacSHA1(policy, this.accessKeySecret) ); } } module.exports = MpUploadOssHelper;
利用组件: flutter_oss_aliyun
flutter_oss_aliyun
页面初始化的时候,调用此方法
static initOss() async { String authorization = "${ProjectConfig.clientId}:${ProjectConfig.clientSecret}"; String base64Authorization = base64Encode(utf8.encode(authorization)); var prefs = await SharedPreferences.getInstance(); Client2.init( stsUrl: '${ProjectConfig.baseUrl}/blade-resource/oss/endpoint/get-acs-param-ali', stsHeader: { 'Authorization': 'Basic ${base64Authorization}', 'Blade-Auth': 'bearer ${prefs.getString("accessToken")}', 'Content-Type': 'application/json' }, ossEndpoint: 'oss-cn-shenzhen.aliyuncs.com', bucketName: 'bucketName'); }
上传文件调用此方法:
XFile? image = await _picker.pickImage(source: ImageSource.gallery,imageQuality: 40);
//获取文件
var file = await image?.readAsBytes();
//获取文件大小
int? size =
file?.lengthInBytes;
String uploadPath='upload/${ProjectConfig.tenantId}/${FunUtils.getNowDate()}/${uuid.v1()}.$extension';
await Client2()
.putObject(
file!,//字节文件
uploadPath,//上传到服务器上的地址
);
main.js
//oss配置
Vue.prototype.aliConfig = {
stsUrl:'/api/blade-resource/oss/endpoint/get-acs-param-ali', // 获取sts服务
region:'oss-cn-shenzhen',
bucket:'bucketName',
tenantId:"000000",//租户id
system:"car",//系统类型
rsUrl:"/api/blade-resource/attach/save" //保存到后台的地址
};
修改avue上传模块源码
avue/packages/element-ui/upload/index.vue
修改源码对比
<template> <div :class="b()" v-loading.lock="loading"> <el-upload :class="b({'list':listType=='picture-img','upload':disabled})" @click.native="handleClick" :action="action" :on-remove="handleRemove" :accept="acceptList" :before-remove="beforeRemove" :multiple="multiple" :on-preview="handlePreview" :limit="limit" :http-request="httpRequest" :drag="drag" :readonly="readonly" :show-file-list="isPictureImg?false:showFileList" :list-type="listType" :on-change="handleFileChange" :on-exceed="handleExceed" :disabled="disabled" :file-list="fileList"> <template v-if="listType=='picture-card'"> <i class="el-icon-plus"></i> </template> <template v-else-if="listType=='picture-img'"> <el-image v-if="imgUrl" :src="imgUrl" :preview-src-list="[imgUrl]" v-bind="allParams" @mouseover="menu=true" :class="b('avatar')"></el-image> <i v-else class="el-icon-plus" :class="b('icon')"></i> <div class="el-upload-list__item-actions" :class="b('menu')" v-if="menu" @mouseover="menu=true" @mouseout="menu=false" @click.stop="()=>{return false}"> <i class="el-icon-zoom-in" @click.stop="handlePreview({url:imgUrl})"></i> <i class="el-icon-delete" v-if="!disabled" @click.stop="handleDelete(imgUrl)"></i> </div> </template> <template v-else-if="drag"> <i class="el-icon-upload"></i> <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div> </template> <template v-else> <el-button size="small" type="primary">点击上传</el-button> </template> <div slot="tip" class="el-upload__tip">{{tip}}</div> </el-upload> <el-dialog append-to-body :class="b('dialog')" top="0" :modal-append-to-body="true" :visible.sync="dialogVisible"> <img v-if="typeList.img.test(dialogUrl)" :src="dialogUrl" style="max-width:100%" alt> <video v-else-if="typeList.video.test(dialogUrl)" controls="controls" style="max-width:100%" :src="dialogUrl"></video> </el-dialog> </div> </template> <script> import create from "core/create"; import props from "../../core/common/props.js"; import event from "../../core/common/event.js"; import { getObjValue } from "utils/util"; import { detailImg } from "plugin/canvas/"; import { getToken } from "plugin/qiniu/"; import { getClient } from "plugin/ali/"; import packages from "core/packages"; export default create({ name: "upload", mixins: [props(), event()], data () { return { menu: false, loading: false, typeList: { img: /(\.(gif|jpg|jpeg|png|GIF|JPG|PNG))|(data:image)/, video: /\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|ogg|mp4)/ }, dialogUrl: "", dialogType: true, dialogVisible: false, text: [], file: {} }; }, props: { data: { type: Object, default: () => { return {} } }, preview: { type: Object, default: () => { } }, value: {}, onRemove: Function, showFileList: { type: Boolean, default: true }, oss: { type: String }, limit: { type: Number, default: 10 }, headers: { type: Object, default: () => { return {} } }, accept: { type: [String, Array], default: "" }, canvasOption: { type: Object, default: () => { return {}; } }, fileSize: { type: Number }, drag: { type: Boolean, default: false }, loadText: { type: String, default: "文件上传中,请稍等" }, action: { type: String, default: "" }, uploadBefore: Function, uploadAfter: Function, uploadDelete: Function, uploadPreview: Function, uploadError: Function }, computed: { acceptList () { if (Array.isArray(this.accept)) { return this.accept.join(',') } return this.accept }, homeUrl () { return this.propsHttp.home || '' }, allParams () { if (this.typeList.video.test(this.imgUrl)) { return Object.assign({ is: 'video' }, this.params) } return this.params }, fileName () { return this.propsHttp.fileName || 'file' }, isAliOss () { return this.oss === "ali"; }, isQiniuOss () { return this.oss === "qiniu"; }, isPictureImg () { return this.listType === "picture-img"; }, //单个头像图片 imgUrl () { if (!this.validatenull(this.text)) { return this.homeUrl + this.text[0]; } }, fileList () { let list = []; const flag = this.isArray || this.isString; (this.text || []).forEach((ele, index) => { if (ele) { let name; //处理单个url链接取最后为label if (flag) { let i = ele.lastIndexOf('/'); name = ele.substring(i + 1); } list.push({ uid: index + '', status: 'done', name: flag ? name : ele[this.labelKey], url: this.homeUrl + (flag ? ele : ele[this.valueKey]) }); } }); return list; } }, created () { }, watch: {}, mounted () { }, methods: { handleClick () { if (typeof this.click === "function") this.click({ value: this.text, column: this.column }); }, handleFileChange (file, fileList) { fileList.splice(fileList.length - 1, 1); if (typeof this.change === "function") this.change({ value: this.text, column: this.column }); }, handleSuccess (file) { if (this.isArray || this.isString) { this.text.push(file[this.urlKey]); } else if (this.isPictureImg) { this.text.splice(0, 1, file[this.urlKey]) } else { let obj = {}; obj[this.labelKey] = file[this.nameKey]; obj[this.valueKey] = file[this.urlKey]; this.text.push(obj); } this.$message.success("上传成功"); }, handleRemove (file, fileList) { this.onRemove && this.onRemove(file, fileList); this.delete(file); this.$message.success("删除成功"); }, handleError (error) { if (typeof this.uploadError === "function") { this.uploadError(error, this.column) } }, delete (file) { if (this.isArray || this.isString) { (this.text || []).forEach((ele, index) => { if (ele === file.url) this.text.splice(index, 1); }); } else { (this.text || []).forEach((ele, index) => { if (ele[this.valueKey] === file.url) this.text.splice(index, 1); }); } }, show (data) { this.loading = false; this.handleSuccess(data); }, hide (msg) { this.loading = false; this.handleError(msg); }, httpRequest (config) { this.loading = true; let file = config.file; const accept = file.type; const fileSize = file.size; this.file = config.file; let acceptList = this.acceptList; if (!Array.isArray(acceptList) && !this.validatenull(acceptList)) { acceptList = acceptList.split(',') } if (!this.validatenull(acceptList) && !acceptList.includes(accept)) { this.hide("文件类型不符合"); return; } if (!this.validatenull(fileSize) && fileSize > this.fileSize) { this.hide("文件太大不符合"); return; } const headers = Object.assign(this.headers, { "Content-Type": "multipart/form-data" }); //oss配置属性 let oss_config = {}; let client = {}; let param = new FormData(); //附加属性 for (let o in this.data) { param.append(o, this.data[o]); } const done = () => { let url = this.action; const callack = async (newFile) => { const uploadfile = newFile || file; param.append(this.fileName, uploadfile); //七牛云oss存储 if (this.isQiniuOss) { if (!window.CryptoJS) { packages.logs("CryptoJS"); this.hide(); return; } oss_config = this.$AVUE.qiniu; const token = getToken(oss_config.AK, oss_config.SK, { scope: oss_config.scope, deadline: new Date().getTime() + oss_config.deadline * 3600 }); param.append("token", token); url = oss_config.bucket } else if (this.isAliOss) { if (!window.OSS) { packages.logs("AliOSS"); this.hide(); return; } // oss_config = this.$AVUE.ali; // "获取当前时间2023-01-12 20:36:55与this.$AVUE.aliExpiration比较" if( this.$AVUE.ali.accessKeyId == "" || (this.$AVUE.aliExpiration&&new Date()>new Date(this.$AVUE.aliExpiration.replace(/\-/g, "/")))){ // let res = this.$axios.get(this.aliConfig.stsUrl); // console.log('res: ', res); await this.$axios.get(this.aliConfig.stsUrl).then(res=>{ let data = res.data.data; let ali = { // yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。 region: this.aliConfig.region, // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。 accessKeyId: data.accessKeyId, accessKeySecret: data.accessKeySecret, // 从STS服务获取的安全令牌(SecurityToken)。 stsToken: data.securityToken, // 填写Bucket名称。 bucket: this.aliConfig.bucket } this.$AVUE.ali = ali; this.$AVUE.aliExpiration = data.expiration; }) } oss_config = this.$AVUE.ali; console.log('oss_config: ', oss_config); client = getClient(oss_config); } (() => { if (this.isAliOss) { let date = new Date(); return client.put("/public/"+this.aliConfig.system+"/"+this.aliConfig.tenantId+"/"+date.getFullYear()+"/"+date.getMonth()+"/"+date.getDate()+"/"+uploadfile.name, uploadfile); // return client.put(uploadfile.name, uploadfile); } else { if (!window.axios) { packages.logs('axios'); return Promise.reject() } return this.$axios.post(url, param, { headers }); } })() .then(async res => { let list = {}; if (this.isQiniuOss) { res.data.key = oss_config.url + res.data.key; } if (this.isAliOss) { let reg2 = new RegExp("/"+res.name); let domainUrl = res.url.replace(reg2,""); let params={ link:res.url, domainUrl:domainUrl, name:res.name, originalName:uploadfile.name, extension:(res.name).split(".")[1], attachSize:uploadfile.size }; await this.$axios.post(this.aliConfig.rsUrl,params).then(res1=>{ list = getObjValue(Object.assign({},res,{attachId:res1.data.data}), this.resKey, "object"); }); } else { list = getObjValue(res.data, this.resKey, "object"); } if (typeof this.uploadAfter === "function") this.uploadAfter( list, () => { this.show(list); }, () => { this.loading = false; }, this.column ); else this.show(list); }) .catch(error => { if (typeof this.uploadAfter === "function") this.uploadAfter(error, this.hide, () => { this.loading = false; }, this.column); else this.hide(error); }); }; if (typeof this.uploadBefore === "function") this.uploadBefore(this.file, callack, () => { this.loading = false; }, this.column); else callack(); }; //是否开启水印 if (!this.validatenull(this.canvasOption)) { detailImg(file, this.canvasOption).then(res => { file = res; done(); }); } else { done(); } }, handleExceed (files, fileList) { this.$message.warning( `当前限制选择 ${this.limit} 个文件,本次选择了 ${ files.length } 个文件,共上传了 ${files.length + fileList.length} 个文件` ); }, handlePreview (file) { const callback = () => { //判断是否为图片 this.dialogUrl = file.url; if (this.typeList.img.test(file.url)) { this.dialogVisible = true; return; } else if (this.typeList.video.test(file.url)) { this.dialogVisible = true; } } if (typeof this.uploadPreview === "function") { this.uploadPreview(file, this.column, callback); } else { callback(); } }, handleDelete (file) { this.beforeRemove(file).then(() => { this.text = []; }).catch(() => { }); }, beforeRemove (file) { if (typeof this.uploadDelete === "function") { return this.uploadDelete(this.column, file); } else { return this.$confirm(`是否确定移除该选项?`); } } } }); </script>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。