当前位置:   article > 正文

若依移动端Ruoyi-App——上传图片使用compressorjs处理图片压缩,自动计算压缩比率,支持h5

compressorjs

背景:

(1)uniapp图片上传存在图片太大,上传时间长的问题,需要将图片压缩上传,

(2)图片压缩比率因大小不同而不同。
(3)uniapp.compressImage不支持h5,而且只能压缩jpg文件

解决方案:

’本文使用uniapp的uni-file-picker进行图片上传,uview的图片上传也可以参考使用。

(1)先把图片都转换为jpg格式文件

(2 )然后计算压缩比率。压缩率compressorjs使用的范围是0-1,uniapp.compressImage使用的是0-100,需要转换下。

(3)最后h5压缩使用compressorjs,非h5压缩使用uniapp.compressImage。

(4)部署到服务器,修改nginx默认长传文件的大小

经验证,本程序只支持h5,小程序uniapp.compressImage只支持jpg文件。

如需支持h5,小程序,app,请转若依移动端Ruoyi-App——使用helang-compress组件压缩上传图片,支持App,小程序,h5,也支持各类格式图片文件。_鲸鱼姐的博客-CSDN博客

效果如下

 

1. 图片压缩首先安装compressorjs

npm install compressorjs --save

2. 创建imageCompress.js,使用图片压缩,本文压缩后返回的类型是blob

  1. import Compressor from 'compressorjs';
  2. // 只能对jpeg格式的图片进行转换
  3. /**
  4. * @param image 图片
  5. * @param backType 需要返回的类型blob,file
  6. * @param quality 图片压缩比 0-1,数字越小,图片压缩越小
  7. * @returns
  8. */
  9. export default function ImageCompressor(image, backType, quality) {
  10. return new Promise((resolve, reject) => {
  11. new Compressor(image, {
  12. quality: quality || 0.6,
  13. success(result) {
  14. let file = new File([result], image.name, { type: image.type })
  15. if (!backType || backType == 'blob') {
  16. resolve(result)
  17. } else if (backType == 'file') {
  18. resolve(file)
  19. } else {
  20. resolve(file)
  21. }
  22. },
  23. error(err) {
  24. console.log('图片压缩失败---->>>>>', err)
  25. reject(err)
  26. }
  27. })
  28. })
  29. }

3. 创建ConvertImage.js将非jpeg图片转化成jpeg图片

  1. // 思路是创建一个图片,将file等于这个图片,然后创建一个canvas图层 ,将canvas等比例缩放,
  2. //然后用canvas的drawImage将图片与canvas合起来,然后在把canvas的base64转成file即可
  3. export default function ConvertImage(file) {
  4. return new Promise((resolve, reject) => {
  5. const fileName = file.name.substring(0, file.name.indexOf('.'));
  6. let reader = new FileReader(); //读取file
  7. reader.readAsDataURL(file);
  8. reader.onloadend = function (e) {
  9. let image = new Image() //新建一个img标签(还没嵌入DOM节点)
  10. image.src = e.target.result //将图片的路径设成file路径
  11. image.onload = function () {
  12. let canvas = document.createElement('canvas'),
  13. context = canvas.getContext('2d'),
  14. imageWidth = image.width,
  15. imageHeight = image.height,
  16. data = ''
  17. canvas.width = imageWidth
  18. canvas.height = imageHeight
  19. context.drawImage(image, 0, 0, imageWidth, imageHeight)
  20. data = canvas.toDataURL('image/jpeg')
  21. var newfile = dataURLtoFile(data, fileName + '.jpeg');
  22. resolve(newfile)
  23. }
  24. }
  25. })
  26. }
  27. function dataURLtoFile(dataurl, filename) { // base64file对象
  28. let arr = dataurl.split(','),
  29. mime = arr[0].match(/:(.*?);/)[1],
  30. bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  31. while (n--) {
  32. u8arr[n] = bstr.charCodeAt(n);
  33. }
  34. return new File([u8arr], filename, { type: mime }); //转成了jpeg格式
  35. }

3. 图片压缩页面的代码如下

  1. <template>
  2. <view class="u-page">
  3. <view class="u-demo-block">
  4. <view class="u-demo-block__content">
  5. <!-- 注意,如果需要兼容微信小程序,最好通过setRules方法设置rules规则 -->
  6. <u--form
  7. labelPosition="left"
  8. :model="form"
  9. ref="form1"
  10. >
  11. <u-form-item
  12. label="选择照片"
  13. prop="form.problemDescription"
  14. borderBottom
  15. labelWidth="80"
  16. ref="item3"
  17. >
  18. <uni-file-picker
  19. :source-type="sourceType"
  20. :sizeType="sizeType"
  21. v-model="fileList1"
  22. mode="grid"
  23. @select="select"
  24. @progress="progress"
  25. @success="success"
  26. @delete ="deletephoto"
  27. @fail="fail"
  28. ref="upload"
  29. limit="9"
  30. />
  31. </uni-file-picker>
  32. </u-form-item>
  33. </u--form>
  34. </view>
  35. </view>
  36. </view>
  37. </template>
  38. <script>
  39. import { getToken } from "@/utils/auth";
  40. import ImageCompressor from "@/utils/imageCompressor"
  41. import ConvertImage from "@/utils/ConvertImage"
  42. import config from '@/config'
  43. export default {
  44. data() {
  45. return {
  46. sourceType: ['album', 'camera'],
  47. sizeType: ['compressed'],
  48. fileMaxSize: 2 * 1024 * 1024, // 默认最大为2M
  49. fileMinSize: 50 * 1024, // 最小为50KB
  50. form: {},
  51. fileList1: {},
  52. imgSrc:{},
  53. images: [],
  54. }
  55. },
  56. onReady() {
  57. },
  58. mounted() {
  59. // this.nowTimes()
  60. },
  61. onLoad(option) {
  62. },
  63. methods: {
  64. // // 选择上传触发函数
  65. async select(e) {
  66. // 根据所选图片的个数,多次调用上传函数
  67. this.btndisabled = true;
  68. this.loadingflag = true;
  69. console.log("select")
  70. console.log(e.tempFilePaths)
  71. let promises=[]
  72. for (let i = 0; i < e.tempFilePaths.length; i++) {
  73. let imgtemp=e.tempFiles[i].file
  74. console.log('img')
  75. console.log(e)
  76. const fileName = imgtemp.name ?? ''
  77. let url =imgtemp.path
  78. const fileType = fileName.substring(fileName.indexOf('.') + 1);
  79. console.log(fileType)
  80. // 判断文件是不是jpeg 不是jpeg的都转成jpeg
  81. if (!['jpeg', 'jpg'].includes(fileType)) {
  82. console.log(fileType)
  83. imgtemp = await ConvertImage(imgtemp); //转陈jpeg格式的file
  84. }
  85. const fileSize = imgtemp.size
  86. if (fileSize > this.fileMaxSize) {
  87. const compressionRatio = this.getCompressionRatio(fileSize)
  88. if (compressionRatio > 1) {
  89. uni.$u.toast('文件' + fileName + '大于10M')
  90. return false
  91. }
  92. console.log('压缩前文件' + fileName + '==compressionRatio'+compressionRatio+'===大小'+fileSize)
  93. // #ifdef H5
  94. imgtemp = await ImageCompressor(imgtemp, 'blob', compressionRatio); //图片压缩
  95. console.log('压缩后文件' + imgtemp.fileName + '====大小'+imgtemp.size)
  96. url = window.URL.createObjectURL(imgtemp)
  97. // #endif
  98. // #ifndef H5
  99. this.compressImg(e.tempFilePaths[i],compressionRatio*100,url)
  100. // #endif
  101. }
  102. console.log('压缩后文件' + url)
  103. const promise =this.uploadFiles(url)
  104. promises.push(promise)
  105. }
  106. Promise.all(promises).then(()=>{
  107. })
  108. },
  109. // 图片压缩
  110. compressImg(tempFilePath,compressionRatio,url){
  111. uni.compressImage({
  112. src: tempFilePath,
  113. quality: compressionRatio,
  114. success: info => {
  115. url=info.tempFilePath
  116. }
  117. })
  118. },
  119. // 图片压缩比例计算
  120. getCompressionRatio(fileSize) {
  121. const multiple = (fileSize / this.fileMaxSize).toFixed(2) // 获取文件大小倍数,生成质量比
  122. let compressionRatio = 1
  123. if(multiple > 5) {
  124. compressionRatio = 0.5
  125. } else if (multiple > 4) {
  126. compressionRatio = 0.6
  127. } else if (multiple > 3) {
  128. compressionRatio = 0.7
  129. }else if (multiple > 2) {
  130. compressionRatio = 0.8
  131. } else if (multiple > 1) {
  132. compressionRatio = 0.9
  133. } else {
  134. compressionRatio = 2
  135. }
  136. return compressionRatio;
  137. },
  138. // 上传函数
  139. async uploadFiles(tempFilePath){
  140. const baseUrl = config.baseUrl
  141. let that =this
  142. await uni.uploadFile({
  143. url: baseUrl+'/common/upload', //后端用于处理图片并返回图片地址的接口
  144. filePath:tempFilePath,
  145. name: 'file',
  146. header: {
  147. Authorization: "Bearer " + getToken(),
  148. },
  149. success: res => {
  150. let data=JSON.parse(res.data) //返回的是字符串,需要转成对象格式
  151. let imageName=data.fileName
  152. that.images.push(imageName)
  153. console.log(that.images)
  154. uni.showToast({ title: '上传成功', icon: "success" });
  155. this.btndisabled = false;
  156. this.loadingflag = false;
  157. },
  158. fail: () => {
  159. console.log("上传失败");
  160. uni.showToast({ title: '上传失败', icon: "error" });
  161. }
  162. })
  163. },
  164. // 移出图片函数
  165. async deletephoto(){
  166. this.fileList1 = {}
  167. },
  168. submit() {
  169. console.log(this.images)
  170. this.form.problemPhotos=this.images.join(',');
  171. addProblems(this.form).then(response => {
  172. this.$modal.msgSuccess("新增成功");
  173. })
  174. }).catch(errors => {
  175. uni.$u.toast('请扫码,填写问题,上传照片')
  176. })
  177. },
  178. }
  179. }
  180. </script>

(1)压缩比率计算

  1. getCompressionRatio(fileSize) {
  2. const multiple = (fileSize / this.fileMaxSize).toFixed(2) // 获取文件大小倍数,生成质量比
  3. alert(fileSize+"==="+this.fileMaxSize+"==="+multiple)
  4. let compressionRatio = 1
  5. if(multiple > 5) {
  6. compressionRatio = 0.5
  7. } else if (multiple > 4) {
  8. compressionRatio = 0.6
  9. } else if (multiple > 3) {
  10. compressionRatio = 0.7
  11. }else if (multiple > 2) {
  12. compressionRatio = 0.8
  13. } else if (multiple > 1) {
  14. compressionRatio = 0.9
  15. } else {
  16. compressionRatio = 2
  17. }
  18. return compressionRatio;
  19. },

(2)压缩

  1. // #ifdef H5
  2. imgtemp = await ImageCompressor(imgtemp, 'blob', compressionRatio); //图片压缩
  3. console.log('压缩后文件' + imgtemp.fileName + '====大小'+imgtemp.size)
  4. url = window.URL.createObjectURL(imgtemp)
  5. // #endif
  6. // #ifndef H5
  7. this.compressImg(e.tempFilePaths[i],compressionRatio*100,url)
  8. // #endif

(3)H5压缩后是blob,需要转bloburl

使用uni.uploadFile上传文件,filePath使用的是bloburl本地地址,blob:http://localhost:9092/e9a9042b-feab-4fed-99ff-81c1e6efdece

  1.   uni.uploadFile({
  2.                      url: '/prod-api/common/upload', //后端用于处理图片并返回图片地址的接口    
  3.                      filePath:tempFilePath,  
  4. ...  
  5. })

因此需要将压缩后的blob文件转换成bloburl,这样才能展示及上传

 let url = window.URL.createObjectURL(newImg)

4.部署到服务器,修改nginx默认长传文件的大小

部署到服务器,出现 Request Entity Too Large问题

通过nginx发现服务代理的,问题就出现nginx服务器上,原来nginx默认长传文件的大小是1M,可在nginx的配置中修改。

解决方法:

(1)打开nginx服务的配置文件nginx.conf, 路径一般是:/usr/local/nginx/conf/nginx.conf。

(2)在http{}中加入client_max_body_size 100m,我这里配置的是100M。

http {
client_max_body_size 100m;
    include       mime.types;
    default_type  application/octet-stream;

(3)重新nginx服务。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/360180
推荐阅读
相关标签
  

闽ICP备14008679号