Browse Source

修改动态发布、添加oss文件上传

master
前端-胡立永 11 months ago
parent
commit
c5e7c08025
13 changed files with 590 additions and 34 deletions
  1. +22
    -0
      components/base/fileUpload.vue
  2. +0
    -10
      config.js
  3. +11
    -0
      main.js
  4. +1
    -1
      manifest.json
  5. +16
    -21
      pages/publish/publishPost.vue
  6. +2
    -2
      utils/index.js
  7. +95
    -0
      utils/oss-upload/common/crypto/base64.js
  8. +117
    -0
      utils/oss-upload/common/crypto/crypto.js.js
  9. +29
    -0
      utils/oss-upload/common/crypto/hmac.js
  10. +59
    -0
      utils/oss-upload/common/crypto/sha1.js
  11. +36
    -0
      utils/oss-upload/oss/OSSConfig.js
  12. +139
    -0
      utils/oss-upload/oss/index.js
  13. +63
    -0
      utils/oss-upload/oss/web.js

+ 22
- 0
components/base/fileUpload.vue View File

@ -0,0 +1,22 @@
<template>
<view>
123
</view>
</template>
<script>
export default {
name:"imageList",
data() {
return {
};
}
}
</script>
<style lang="scss" scoped>
.a{
width: 100rpx;
}
</style>

+ 0
- 10
config.js View File

@ -3,8 +3,6 @@ import Vue from 'vue'
import api from '@/api/api.js' import api from '@/api/api.js'
import utils from './utils/utils.js' import utils from './utils/utils.js'
import uvUI from '@/uni_modules/uv-ui-tools'
Vue.use(uvUI);
// 当前环境 // 当前环境
const type = 'dev' const type = 'dev'
@ -41,14 +39,6 @@ const defaultConfig = {
} }
uni.$uv.setConfig({
// 修改$uv.config对象的属性
config: {
// 修改默认单位为rpx,相当于执行 uni.$uv.config.unit = 'rpx'
unit: 'rpx'
},
})
Vue.prototype.$config = utils.deepMergeObject(defaultConfig, config[type]) Vue.prototype.$config = utils.deepMergeObject(defaultConfig, config[type])
Vue.prototype.$api = api Vue.prototype.$api = api


+ 11
- 0
main.js View File

@ -15,6 +15,17 @@ import i18n from './locale/index.js'
import './config' import './config'
import './utils/index.js' import './utils/index.js'
import uvUI from '@/uni_modules/uv-ui-tools'
Vue.use(uvUI);
uni.$uv.setConfig({
// 修改$uv.config对象的属性
config: {
// 修改默认单位为rpx,相当于执行 uni.$uv.config.unit = 'rpx'
unit: 'rpx'
},
})
//组件注册 //组件注册
import configPopup from '@/components/config/configPopup.vue' import configPopup from '@/components/config/configPopup.vue'
import changeLanguage from '@/components/base/changeLanguage.vue' import changeLanguage from '@/components/base/changeLanguage.vue'


+ 1
- 1
manifest.json View File

@ -52,7 +52,7 @@
"quickapp" : {}, "quickapp" : {},
/* */ /* */
"mp-weixin" : { "mp-weixin" : {
"appid" : "wxe7ae8cbe1673834c",
"appid" : "wx3c24e397e3b132ea",
"setting" : { "setting" : {
"urlCheck" : false, "urlCheck" : false,
"ignoreDevUnusedFiles" : false "ignoreDevUnusedFiles" : false


+ 16
- 21
pages/publish/publishPost.vue View File

@ -6,14 +6,6 @@
title="发布帖子"/> title="发布帖子"/>
<view class="images box"> <view class="images box">
<!-- <view class="image"
v-for="(src, index) in form.image"
:key="index">
<image src="src" mode=""></image>
</view>
<view class="add">
<uv-icon name="plus"></uv-icon>
</view> -->
<uv-upload <uv-upload
:fileList="fileList" :fileList="fileList"
:maxCount="5" :maxCount="5"
@ -35,12 +27,12 @@
:maxlength="200" :maxlength="200"
autoHeight autoHeight
count count
placeholder="添加标题"></uv-textarea>
placeholder="添加正文"></uv-textarea>
</view> </view>
<view class="upTop"> <view class="upTop">
<view class="title"> <view class="title">
<!-- <uv-icon name=""></uv-icon> -->
<uv-icon name="pushpin-fill"></uv-icon>
是否置顶 是否置顶
</view> </view>
<uv-radio-group v-model="form.upTop"> <uv-radio-group v-model="form.upTop">
@ -75,10 +67,12 @@
<script> <script>
import submit from '@/components/content/submit.vue' import submit from '@/components/content/submit.vue'
import uvUpload from '@/uni_modules/uv-upload/components/uv-upload/uv-upload.vue' import uvUpload from '@/uni_modules/uv-upload/components/uv-upload/uv-upload.vue'
import fileUpload from '@/components/base/fileUpload.vue'
export default { export default {
components : { components : {
submit, submit,
uvUpload
fileUpload,
uvUpload,
}, },
data() { data() {
return { return {
@ -106,16 +100,6 @@
upTop : '', upTop : '',
}, },
fileList: [ fileList: [
{
url: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
name : '132',
},
{
url: 'https://cdn.uviewui.com/uview/swiper/2.jpg'
},
{
url: 'https://cdn.uviewui.com/uview/swiper/2.jpg'
},
{ {
url: 'https://cdn.uviewui.com/uview/swiper/2.jpg' url: 'https://cdn.uviewui.com/uview/swiper/2.jpg'
}, },
@ -123,6 +107,15 @@
}; };
}, },
methods : { methods : {
//
uploadImage(){
let self = this
this.$Oss.ossUploadImage({
success(res){
self.form.images.push(res)
}
})
},
deleteImage(e){ deleteImage(e){
this.fileList.splice(e.index, 1) this.fileList.splice(e.index, 1)
}, },
@ -169,6 +162,8 @@
padding-top: 20rpx; padding-top: 20rpx;
padding-left: 30rpx; padding-left: 30rpx;
border-top: 1px solid #00000015; border-top: 1px solid #00000015;
display: flex;
align-items: center;
} }
.list{ .list{
padding-top: 30rpx; padding-top: 30rpx;


+ 2
- 2
utils/index.js View File

@ -18,11 +18,11 @@ Vue.prototype.$wxPay = wxPay
// dayjs.locale('zh-cn') // dayjs.locale('zh-cn')
import uploadFileToOSS from './upload.js'
import Oss from '@/utils/oss-upload/oss/index.js'
import { handleTree } from './tree.js' import { handleTree } from './tree.js'
Vue.prototype.$handleTree = handleTree Vue.prototype.$handleTree = handleTree
Vue.prototype.$uploadFileToOSS = uploadFileToOSS
Vue.prototype.$Oss = Oss
Vue.prototype.$dayjs = dayjs Vue.prototype.$dayjs = dayjs
Vue.prototype.$timeUtils = time Vue.prototype.$timeUtils = time


+ 95
- 0
utils/oss-upload/common/crypto/base64.js View File

@ -0,0 +1,95 @@
export const Base64 = {
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function(input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
decode: function(input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
_utf8_encode: function(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
_utf8_decode: function(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if ((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i + 1);
c3 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

+ 117
- 0
utils/oss-upload/common/crypto/crypto.js.js View File

@ -0,0 +1,117 @@
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let Crypto = {};
var util = Crypto.util = {
rotl: function(n, b) {
return (n << b) | (n >>> (32 - b));
},
rotr: function(n, b) {
return (n << (32 - b)) | (n >>> b);
},
endian: function(n) {
if (n.constructor == Number) {
return util.rotl(n, 8) & 0x00FF00FF |
util.rotl(n, 24) & 0xFF00FF00;
}
for (var i = 0; i < n.length; i++)
n[i] = util.endian(n[i]);
return n;
},
randomBytes: function(n) {
for (var bytes = []; n > 0; n--)
bytes.push(Math.floor(Math.random() * 256));
return bytes;
},
stringToBytes: function(str) {
var bytes = [];
for (var i = 0; i < str.length; i++)
bytes.push(str.charCodeAt(i));
return bytes;
},
bytesToString: function(bytes) {
var str = [];
for (var i = 0; i < bytes.length; i++)
str.push(String.fromCharCode(bytes[i]));
return str.join("");
},
stringToWords: function(str) {
var words = [];
for (var c = 0, b = 0; c < str.length; c++, b += 8)
words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32);
return words;
},
bytesToWords: function(bytes) {
var words = [];
for (var i = 0, b = 0; i < bytes.length; i++, b += 8)
words[b >>> 5] |= bytes[i] << (24 - b % 32);
return words;
},
wordsToBytes: function(words) {
var bytes = [];
for (var b = 0; b < words.length * 32; b += 8)
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
return bytes;
},
bytesToHex: function(bytes) {
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join("");
},
hexToBytes: function(hex) {
var bytes = [];
for (var c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
},
bytesToBase64: function(bytes) {
if (typeof btoa == "function") return btoa(util.bytesToString(bytes));
var base64 = [],
overflow;
for (var i = 0; i < bytes.length; i++) {
switch (i % 3) {
case 0:
base64.push(base64map.charAt(bytes[i] >>> 2));
overflow = (bytes[i] & 0x3) << 4;
break;
case 1:
base64.push(base64map.charAt(overflow | (bytes[i] >>> 4)));
overflow = (bytes[i] & 0xF) << 2;
break;
case 2:
base64.push(base64map.charAt(overflow | (bytes[i] >>> 6)));
base64.push(base64map.charAt(bytes[i] & 0x3F));
overflow = -1;
}
}
if (overflow != undefined && overflow != -1)
base64.push(base64map.charAt(overflow));
while (base64.length % 4 != 0) base64.push("=");
return base64.join("");
},
base64ToBytes: function(base64) {
if (typeof atob == "function") return util.stringToBytes(atob(base64));
base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
var bytes = [];
for (var i = 0; i < base64.length; i++) {
switch (i % 4) {
case 1:
bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) |
(base64map.indexOf(base64.charAt(i)) >>> 4));
break;
case 2:
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) |
(base64map.indexOf(base64.charAt(i)) >>> 2));
break;
case 3:
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) |
(base64map.indexOf(base64.charAt(i))));
break;
}
}
return bytes;
}
};
Crypto.mode = {};
export default Crypto;

+ 29
- 0
utils/oss-upload/common/crypto/hmac.js View File

@ -0,0 +1,29 @@
import Crypto from '@/utils/oss-upload/common/crypto/crypto.js.js';
(function() {
// Shortcut
var util = Crypto.util;
Crypto.HMAC = function(hasher, message, key, options) {
// Allow arbitrary length keys
key = key.length > hasher._blocksize * 4 ?
hasher(key, {
asBytes: true
}) :
util.stringToBytes(key);
// XOR keys with pad constants
var okey = key,
ikey = key.slice(0);
for (var i = 0; i < hasher._blocksize * 4; i++) {
okey[i] ^= 0x5C;
ikey[i] ^= 0x36;
}
var hmacbytes = hasher(util.bytesToString(okey) +
hasher(util.bytesToString(ikey) + message, {
asString: true
}), {
asBytes: true
});
return options && options.asBytes ? hmacbytes :
options && options.asString ? util.bytesToString(hmacbytes) :
util.bytesToHex(hmacbytes);
};
})();

+ 59
- 0
utils/oss-upload/common/crypto/sha1.js View File

@ -0,0 +1,59 @@
import Crypto from '@/utils/oss-upload/common/crypto/crypto.js.js';
(function() {
// Shortcut
var util = Crypto.util;
// Public API
var SHA1 = Crypto.SHA1 = function(message, options) {
var digestbytes = util.wordsToBytes(SHA1._sha1(message));
return options && options.asBytes ? digestbytes :
options && options.asString ? util.bytesToString(digestbytes) :
util.bytesToHex(digestbytes);
};
// The core
SHA1._sha1 = function(message) {
var m = util.stringToWords(message),
l = message.length * 8,
w = [],
H0 = 1732584193,
H1 = -271733879,
H2 = -1732584194,
H3 = 271733878,
H4 = -1009589776;
// Padding
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >>> 9) << 4) + 15] = l;
for (var i = 0; i < m.length; i += 16) {
var a = H0,
b = H1,
c = H2,
d = H3,
e = H4;
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = m[i + j];
else {
var n = w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16];
w[j] = (n << 1) | (n >>> 31);
}
var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + (
j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 :
j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 :
j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 :
(H1 ^ H2 ^ H3) - 899497514);
H4 = H3;
H3 = H2;
H2 = (H1 << 30) | (H1 >>> 2);
H1 = H0;
H0 = t;
}
H0 += a;
H1 += b;
H2 += c;
H3 += d;
H4 += e;
}
return [H0, H1, H2, H3, H4];
};
// Package private blocksize
SHA1._blocksize = 16;
})();

+ 36
- 0
utils/oss-upload/oss/OSSConfig.js View File

@ -0,0 +1,36 @@
import Crypto from '@/utils/oss-upload/common/crypto/crypto.js.js';
import '@/utils/oss-upload/common/crypto/hmac.js';
import '@/utils/oss-upload/common/crypto/sha1.js';
import { Base64 } from '@/utils/oss-upload/common/crypto/base64.js';
import ossConfig from '@/config.js'
let date = new Date()
date = date.setHours(date.getHours() + 1)
let extime = "" + new Date(date).toISOString()
let policyText = {
"expiration": extime,
"conditions": [
["content-length-range", 0, 1024 * 1024 * 100] // 设置上传文件的大小限制
]
};
let config = {
accessid: ossConfig.aliOss.config.accessKeyId,
accesskey: ossConfig.aliOss.config.accessKeySecret,
osshost: ossConfig.aliOss.url,
policyBase64: Base64.encode(JSON.stringify(policyText))
}
let message = config.policyBase64;
let bytes = Crypto.HMAC(Crypto.SHA1, message, config.accesskey, {
asBytes: true
});
let signature = Crypto.util.bytesToBase64(bytes);
let timetamp = new Date().getTime();
let OSSConfig = {
name: 'aliyun',
host: config.osshost,
accessid: config.accessid,
signature: signature,
policyBase64: config.policyBase64,
}
export default OSSConfig;

+ 139
- 0
utils/oss-upload/oss/index.js View File

@ -0,0 +1,139 @@
/**
* 阿里云OSS工具类
*/
import OSSConfig from "@/utils/oss-upload/oss/OSSConfig.js"
//支持web端
import {
uploadFileToOSS
} from '@/utils/oss-upload/oss/web.js'
import ossConfig from '@/config.js'
/**
* 生成一个随机的Key
*/
function storeKey() {
let s = [];
let hexDigits = "0123456789abcdef";
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
return s.join("");
}
/**
* 根据当天日期在OSS端生成文件夹
*/
function storeFolder() {
const date = new Date();
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
return [date.getFullYear(), date.getMonth() + 1, date.getDate()].map(formatNumber).join('-')
}
/**
* 阿里云OSS上传文件, 所有具体功能的工具函数均基于此
* 注意, resolve时一定为上传成功, 返回OSS上的Key
* @param filePath 待上传文件的URI
* @param key 存储桶中的目标文件名
* @param folder 存储桶中的目标文件夹
*/
export function ossUpload(filePath, key = storeKey(), folder = storeFolder()) {
return new Promise((resolve, reject) => {
if (folder && folder?.length > 0) {
if (folder[0] == "/") folder = folder.slice(1, folder.length)
if (folder[folder.length - 1] != "/") folder += "/"
key = folder + key
}
const filePrefixArr = filePath.split(".")
key += `.${filePrefixArr[filePrefixArr.length - 1]}`
let config = {
url: OSSConfig.host,
name: 'file',
filePath,
formData: {
key,
policy: OSSConfig.policyBase64,
OSSAccessKeyId: OSSConfig.accessid,
success_action_status: '200',
signature: OSSConfig.signature,
},
success(res) {
if (res.errMsg.includes("uploadFile:ok")) {
resolve(ossConfig.aliOss.url + key)
} else {
reject(res)
}
},
fail(err) {
reject(err)
}
}
uni.uploadFile(config)
})
}
/**
* 阿里云OSS上传图片
* @param {compressed, key, folder, success, fail} compressed: 是否压缩 key: 存储桶中的目标文件名 folder: 存储桶中的目标文件夹
*/
export function ossUploadImage({
key,
folder,
compressed = true, //是否压缩
success, //成功时的回调
fail //失败时的回调
}) {
const sizeType = [compressed ? 'compressed' : 'original']
uni.chooseImage({
count: 1,
sizeType,
success(res) {
// #ifdef H5
return uploadFileToOSS(res.tempFiles[0]).then(success).catch(fail)
// #endif
ossUpload(res.tempFilePaths[0], key, folder).then(success).catch(fail)
},
fail
})
}
/**
* 阿里云OSS上传视频
* @param { key, folder, sourceType, compressed, maxDuration, camera, success, fail}
* key: 存储桶中的目标文件名 folder: 存储桶中的目标文件夹 其它参数同uni.chooseVideo(mpWeixin)
*/
export function ossUploadVideo({
key,
folder,
sourceType = ['album', 'camera'], //album 从相册选视频, camera 使用相机拍摄
compressed = true, //是否压缩所选的视频源文件
maxDuration = 60, //拍摄视频最长拍摄时间, 单位秒。最长支持 60 秒
camera = 'back', //调用相机方向, 'front'、'back', 默认'back'
success, //成功时的回调
fail //失败时的回调
}) {
uni.chooseVideo({
sourceType,
compressed,
maxDuration,
camera,
success(res) {
// #ifdef H5
return uploadFileToOSS(res.tempFile).then(success).catch(fail)
// #endif
ossUpload(res.tempFilePath, key, folder).then(success).catch(fail)
},
fail
})
}
const OSS = {
ossUploadVideo,
ossUploadImage,
ossUpload
}
export default OSS;

+ 63
- 0
utils/oss-upload/oss/web.js View File

@ -0,0 +1,63 @@
// 此方法适用于web
import OSS from "ali-oss"
import config from '@/config.js'
/**
* 生成一个随机的Key
*/
function storeKey() {
let s = [];
let hexDigits = "0123456789abcdef";
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
return s.join("");
}
/**
* 根据当天日期在OSS端生成文件夹
*/
function storeFolder() {
const date = new Date();
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
return [date.getFullYear(), date.getMonth() + 1, date.getDate()].map(formatNumber).join('-')
}
export function uploadFileToOSS(file) {
uni.showLoading({
title: '上传中...'
});
return new Promise((resolve,reject) => {
// 创建OSS实例
const client = new OSS(config.aliOss.config);
// 设置文件名和文件目录
const suffix = '.' + file.name.split('.').pop();
let key = storeFolder()
if(key[key.length - 1] != '/') key += '/'
const fileName = key + storeKey() + suffix; // 注意:文件名需要是唯一的
// 使用put接口上传文件
client.multipartUpload(fileName, file, {
headers: {
'Content-Disposition': 'inline',
'Content-Type': file.type
}
}).then(res => {
uni.hideLoading();
resolve(config.aliOss.url + res.name);
}).catch(err => {
uni.hideLoading();
reject(err)
})
})
}

Loading…
Cancel
Save