uniappH5图片压缩上传
此篇文章只供自己参考 我只是代码的搬运工
1.uniapp插件市场中的压缩插件
转载自uniapp插件市场
2.将压缩完返回的base64文件转为临时文件的js文件(可根据项目要求是否需要,不需要的话可跳过此步骤)
转载自uniapp插件市场
具体代码如下:
压缩图片组件代码
<template>
<view class="image-compress-container">
<!-- #ifndef H5 -->
<canvas :style="{width: W + 'px', height: H + 'px', visibility: 'hidden'}" class="canvas" canvas-id="canvas"></canvas>
<!-- #endif -->
</view>
</template>
<script>
export default {
data () {
return {
W: '',
H: '',
canvas: null,
ctx: null,
maxW: 1024,
maxH: 1024,
quality: 0.8,
base64: false,
showLoading: '正在压缩',
mask: true
}
},
methods: {
async compress (args, options = {}) {
return new Promise(async (resolve, reject) => {
let files;
if (arguments[0].tempFiles || arguments[0].tempFilePaths) {
files = arguments[0].tempFilePaths || arguments[0].tempFiles;
};
if (arguments[0].files) {
files = arguments[0].files;
}
if (!files instanceof Array) {
reject('数据格式错误');
}
if (!files.length) {
reject('数据不能为空');
}
this.maxW = options.maxW || 1024;
this.maxH = options.maxH || 1024;
this.quality = options.quality || 0.8;
this.base64 = options.base64 || false;
this.showLoading = options.showLoading === true ? '正在压缩' : typeof options.showLoading === 'string' ? options.showLoading : false;
this.mask = options.mask || true;
if (this.showLoading) {
uni.showLoading({
title: this.showLoading,
mask: this.mask
})
}
try {
const result = await this.convertImageToBase64(files);
resolve(result);
uni.hideLoading();
} catch (error) {
reject(error);
uni.hideLoading();
}
})
},
toBase64H5 (file) {
return new Promise((resolve, reject) => {
let result = [];
for (let i = 0; i < file.length; i++) {
let reader = new FileReader();
let base64Result;
reader.addEventListener('load', (e) => {
base64Result = reader.result || e.target.result;
let filename = file[i].name.slice(0, file[i].name.lastIndexOf('.'));
result.push({base64: base64Result, filename});
reader = null;
if (result.length === file.length) {
resolve(result);
}
});
reader.readAsDataURL(file[i]);
}
})
},
compressResultH5 (base64Item) {
return new Promise((resolve, reject) => {
let maxW = this.maxW;
let maxH = this.maxH;
let ratio, needCompress = false;
let image = new Image();
image.src = base64Item.base64;
image.addEventListener('load', () => {
if (image.naturalWidth > maxW) {
needCompress = true;
ratio = image.naturalWidth / maxW;
maxH = image.naturalHeight / ratio;
}
if (image.naturalHeight > maxH) {
needCompress = true;
ratio = image.naturalHeight / maxH;
maxW = image.naturalWidth / ratio;
}
if (!needCompress) {
maxW = image.naturalWidth;
maxH = image.naturalWidth;
}
if (!this.canvas) {
this.canvas = document.createElement('canvas');
}
this.canvas.width = maxW;
this.canvas.height = maxH;
const ctx = this.canvas.getContext('2d');
ctx.clearRect(0, 0, maxW, maxH);
ctx.drawImage(image, 0, 0, maxW, maxH);
const compressImg = this.canvas.toDataURL('image/jpeg', this.quality);
let file = this._dataURLtoFile(compressImg, base64Item.filename);
if (this.base64) {
resolve({base64: compressImg, file});
} else {
resolve({file});
}
image = null;
// ratio: base64Item.base64.length / compressImg.length
})
})
},
compressImageH5 (base64Result) {
let result = [];
return new Promise(async (resolve, reject) => {
for (let i = 0; i < base64Result.length; i++) {
let res = await this.compressResultH5(base64Result[i]);
result.push(res);
if (result.length === base64Result.length) {
resolve(result);
this.canvas = null;
}
}
})
},
async convertImageToBase64 (files) {
// #ifdef H5
if (typeof files[0] === 'object') {
let result = await this.toBase64H5(files);
return await this.compressImageH5(result);
}
if (typeof files[0] === 'string') {
let result = files.map(item => {
return {
base64: item
}
});
return await this.compressImageH5(result);
}
return [];
// #endif
// #ifndef H5
if (typeof files[0] === 'string') {
const result = await this.getImgInfoWX(files);
return await this.compressImageWX(result);
}
if (typeof files[0] === 'object') {
files = files.map(item => {
return item.path
});
const result = await this.getImgInfoWX(files);
return await this.compressImageWX(result);
}
return [];
// #endif
return [];
},
getImgInfoWX (tempFilePaths) {
let result = [];
return new Promise((resolve, reject) => {
for (let i = 0; i < tempFilePaths.length; i++) {
uni.getImageInfo({
src: tempFilePaths[i],
success: (image) => {
result.push({tempFilePaths: tempFilePaths[i], image});
if (result.length === tempFilePaths.length) {
resolve(result);
}
}
});
}
})
},
compressResultWX (tempFilePaths) {
return new Promise((resolve, reject) => {
let maxW = this.maxW;
let maxH = this.maxH;
let ratio, needCompress = false;
tempFilePaths.image.width = Number(tempFilePaths.image.width);
tempFilePaths.image.height = Number(tempFilePaths.image.height);
if (tempFilePaths.image.width > maxW) {
needCompress = true;
ratio = tempFilePaths.image.width / maxW;
maxH = tempFilePaths.image.height / ratio;
}
if (tempFilePaths.image.height > maxH) {
needCompress = true;
ratio = tempFilePaths.image.height / maxH;
maxW = tempFilePaths.image.width / ratio;
}
if (!needCompress) {
maxW = tempFilePaths.image.width;
maxH = tempFilePaths.image.height;
}
this.W = maxW;
this.H = maxH;
if (!this.ctx) {
this.ctx = uni.createCanvasContext('canvas', this);
}
this.ctx.clearRect(0, 0, this.W, this.H);
this.ctx.drawImage(tempFilePaths.tempFilePaths, 0, 0, maxW, maxH);
setTimeout(()=>{
this.ctx.draw(false, () => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: this.W,
height: this.H,
destWidth: this.W,
destHeight: this.H,
canvasId: 'canvas',
quality: this.quality,
success: (res) => {
let file = res.tempFilePath;
let base64 = uni.getFileSystemManager().readFileSync(file, 'base64');
base64 = `data:image/jpeg;base64,${base64}`
if (this.base64) {
resolve({file, base64});
} else {
resolve({file});
}
}
}, this)
});
},1500)
})
},
compressImageWX (tempFilePaths) {
let result = [];
return new Promise(async (resolve, reject) => {
for (let i = 0; i < tempFilePaths.length; i++) {
let res = await this.compressResultWX(tempFilePaths[i]);
result.push(res);
if (result.length === tempFilePaths.length) {
resolve(result);
this.ctx = null;
}
}
})
},
_dataURLtoFile (dataurl, filename) {
let arr = dataurl.split(',');
let mime = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
}
}
</script>
<style scoped>
.image-compress-container {
width: 0;
height: 0;
margin: 0;
padding: 0;
overflow: hidden;
position: absolute;
z-index: -100000;
}
</style>
base64文件转为临时文件的js文件(也可以使用npm下载跳过这一步)
function getLocalFilePath(path) {
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
return path
}
if (path.indexOf('file://') === 0) {
return path
}
if (path.indexOf('/storage/emulated/0/') === 0) {
return path
}
if (path.indexOf('/') === 0) {
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substr(1)
}
}
return '_www/' + path
}
function dataUrlToBase64(str) {
var array = str.split(',')
return array[array.length - 1]
}
var index = 0
function getNewFileId() {
return Date.now() + String(index++)
}
function biggerThan(v1, v2) {
var v1Array = v1.split('.')
var v2Array = v2.split('.')
var update = false
for (var index = 0; index < v2Array.length; index++) {
var diff = v1Array[index] - v2Array[index]
if (diff !== 0) {
update = diff > 0
break
}
}
return update
}
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
var xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
var fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export function base64ToPath(base64) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
var type = base64[0].match(/:(.*?);/)[1]
var str = atob(base64[1])
var n = str.length
var array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
}
var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
var fileName = getNewFileId() + '.' + extName
if (typeof plus === 'object') {
var basePath = '_doc'
var dirPath = 'uniapp_temp'
var filePath = basePath + '/' + dirPath + '/' + fileName
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
entry.getDirectory(dirPath, {
create: true,
exclusive: false,
}, function(entry) {
entry.getFile(fileName, {
create: true,
exclusive: false,
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function() {
resolve(filePath)
}
writer.onerror = reject
writer.seek(0)
writer.writeAsBinary(dataUrlToBase64(base64))
}, reject)
}, reject)
}, reject)
}, reject)
return
}
var bitmap = new plus.nativeObj.Bitmap(fileName)
bitmap.loadBase64Data(base64, function() {
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: dataUrlToBase64(base64),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
页面中使用:
<template>
<view>
<view @click="shoot">上传</view>
<x-compress ref="xCompress"></x-compress> // 放到template里就可以 随便放一个地方
</view>
</template>
<script>
import xCompress from '压缩图片组件路径.vue';
import { pathToBase64, base64ToPath } from 'base64文件转为临时文件路径.js'
//npm下载方式
//npm i image-tools --save
//import { pathToBase64, base64ToPath } from 'image-tools'
export default {
data() {
return {
}
},
methods: {
// 点击上传
shoot() {
uni.chooseImage({
sourceType: ['camera','album'],
count : 1,
success: async (res) => {
// console.log('压缩前图片体积', res.tempFiles[0].size);
try {
// 调用组件的compress方法开始压缩
let result = await this.$refs.xCompress.compress(res, {
base64: true, // 是否也返回base64格式,默认false,既不返回base64格式图片数据,反之亦然
maxW: 1024 , // 当图片宽度超过1024大小时最大为1024(高度也会按比例缩放),默认也是1024
maxH: 1024, // 当图片高度超过1024大小时最大为1024(宽度也会按比例缩放),默认也是1024
quality: 0.8, // 压缩质量(0-1),默认为0.8,值越小压缩质量越大
showLoading: true, // 是否显示loading提示,也可以传入一个字符串(相当于loading时的title),默认为true,
mask: true // 当showLoading为true时,是否显示遮罩层,默认为true
});
// console.log('result', result);
// 调用组件的base64ToPath方法转为临时路径
base64ToPath(result[0].base64)
.then(path => {
console.log(path) // 最终图片
})
.catch(error => {
console.error(error)
})
} catch (error) {
console.log('error', error);
}
}
})
},
}
}
</script>