フロントエンド画像直伝アリOSS実現方法
7336 ワード
フロントエンドピクチャダイレクトアリOSSは唯一の解決方法ではなく,バックエンド処理に置くこともできるが,本稿ではフロントエンドピクチャダイレクトアリOSSの実現方式のみを検討する.
#プロセス:
1、OSSを初期化する
2、アップロードした画像を取得する
3、長伝画像
#処理するポイント:
1:ユーザーがアップロードした画像が大きすぎる場合、微損圧縮画像を行う
2:アップルの携帯電話が回転して写真をアップロードすると、回転ずれ(互換性処理)
プロジェクトはvantを採用し、直伝アリossの機能をパッケージし、コードは以下の通りである.
使用方法:
#プロセス:
1、OSSを初期化する
2、アップロードした画像を取得する
3、長伝画像
#処理するポイント:
1:ユーザーがアップロードした画像が大きすぎる場合、微損圧縮画像を行う
2:アップルの携帯電話が回転して写真をアップロードすると、回転ずれ(互換性処理)
プロジェクトはvantを採用し、直伝アリossの機能をパッケージし、コードは以下の通りである.
/**
* Created by SongPeng on 2019-8-9
*/
import OSS from 'ali-oss'
import { getOssUploadRole } from '@/api/wallet'
import { Toast, Dialog } from 'vant'
import { ossUrl } from '@/config'
import EXIF from 'exif-js'
/**
* base64
* @param {*base64} base64URL
*/
export function compressImage (base64URL) {
return new Promise((resolve) => {
let orientation = ''
let img = new Image()
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
img.src = base64URL
img.onload = () => {
//
let originWidth = img.width
let originHeight = img.height
//
let maxWidth = img.width / 2
let maxHeight = img.height / 2
//
// 1000x1000
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
// ,
img.width = maxWidth
img.height = Math.round(maxWidth * (originHeight / originWidth))
} else {
img.height = maxHeight
img.width = Math.round(maxHeight * (originWidth / originHeight))
}
}
// canvas
canvas.width = img.width
canvas.height = img.height
//
ctx.clearRect(0, 0, canvas.width, canvas.height)
EXIF.getData(img, function () {
if (navigator.userAgent.match(/iphone/i)) {
orientation = EXIF.getTag(this, 'Orientation')
switch (Number(orientation)) {
case 2:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.drawImage(img, 0, 0, img.width, img.height)
break
case 3:
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -img.width, -img.height, img.width, img.height)
break
case 4:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -img.width, -img.height, img.width, img.height)
break
case 5:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, -img.width, img.height, img.width)
break
case 6:
canvas.width = img.height
canvas.height = img.width
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, 0, img.width, -img.height)
break
case 7:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -img.height, 0, img.height, img.width)
break
case 8:
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -img.height, 0, img.height, img.width)
break
default:
ctx.drawImage(img, 0, 0, img.width, img.height)
break
}
} else {
ctx.drawImage(img, 0, 0, img.width, img.height)
}
})
let base64 = canvas.toDataURL('image/jpeg', 0.7)
resolve(base64)
}
})
}
/**
* base64 url Blob
* @param urlData base64
* @name convertBase64UrlToBlob
*/
export function convertBase64UrlToBlob (urlData) {
let bytes = window.atob(urlData.split(',')[1]) // url , byte
// , ascii 0 0
let ab = new ArrayBuffer(bytes.length)
let ia = new Uint8Array(ab)
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i)
}
return new Blob([ab], {
type: 'image/jpg'
})
}
/**
* base64 url file
* @param dataurl base64
* @param filename
* @name dataURLtoFile
*/
export function dataURLtoFile (dataurl, filename) { // base64
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, {
type: mime
})
}
const aliOss = {
client: null,
fileName: '',
file: null,
loading: null,
async setClient () {
if (this.client === null) {
const res = await getOssUploadRole()
if (res.code === 0) {
let result = res.data
this.client = new OSS({
accessKeyId: result.accessKeyId,
accessKeySecret: result.accessKeySecret,
stsToken: result.stsToken,
endpoint: result.endpoint,
bucket: result.bucket
})
}
}
},
uploadImg (fileName, file) {
Toast.loading({
mask: true,
duration: 0,
message: ' ...'
})
return new Promise((resolve, reject) => {
this.fileName = fileName
this.file = file
if (file.file.size / 1024 / 1024 > 0.8) {
compressImage(this.file.content)
.then(base64 => {
this.file.file = convertBase64UrlToBlob(base64)
this.readyLoad(this.fileName, this.file.file)
.then(url => {
resolve(url)
})
})
} else {
this.readyLoad(this.fileName, this.file.file)
.then(url => {
resolve(url)
})
}
})
},
readyLoad (fileName, file) {
return new Promise((resolve, reject) => {
this.client.multipartUpload(fileName, file)
.then(function (result) {
Toast.clear()
Toast({
type: 'success',
message: ' ',
duration: 1500
})
resolve(`${ossUrl}/${fileName}`)
})
.catch(function (err) {
Toast.clear()
if (err.indexOf('timeout') !== -1) {
Dialog({
title: ' ',
message: ' '
})
} else {
Dialog({
title: ' ',
message: ' '
})
}
})
})
}
}
export default aliOss
使用方法:
import aliOss from '@/utils/uploadImg' //
this.initOss() // OSS
onRead (file, options) {
const data = file.file.name.split('.')
let imgType = data[data.length - 1]
let fileName = `img/${options.name}-${this.$store.state.userInfo.id}-${Date.parse(new Date())}.${imgType}`
aliOss.uploadImg(fileName, file)
.then(url => {
// oss
this.$store.dispatch('brand/setBrandLogo', url)
.then(res => {
if (res.code === 0) {
this.$Toast.success(res.message)
}
})
})
}