モバイル端末のRuoyi-Appによると、写真をアップロードし、compressorjsを使用して写真の圧縮を処理し、圧縮率を自動的に計算します

バックグラウンド:

(1) uniapp 画像のアップロードが大きすぎてアップロードに時間がかかるという問題があり、画像を圧縮してアップロードする必要があります。

(2) 画像の圧縮率はサイズによって異なります。
(3) uniapp.compressImage は h5 をサポートしておらず、jpg ファイルのみを圧縮できます

解決:

この記事では、uniapp の uni-file-picker を使用して写真をアップロードしていますが、uview の写真のアップロードも参照に使用できます。

(1) まず写真をjpg形式のファイルに変換します

(2) 次に、圧縮率を計算します。compressjs で使用される圧縮率の範囲は 0 ~ 1 であり、uniapp.compressImage で使用される範囲は 0 ~ 100 であり、変換する必要があります。

(3) 最後に、compressorjs は h5 圧縮に使用され、uniapp.compressImage は非 h5 圧縮に使用されます。

(4) サーバーにデプロイし、nginx デフォルトのロングパス ファイルのサイズを変更します

効果は以下の通り

 

1.画像圧縮 まずはcompressorjsをインストール

npm install compressorjs --save

2. imageCompress.js を作成し、画像圧縮を使用する この記事で圧縮後に返される型は blob です

import Compressor from 'compressorjs';
// 只能对jpeg格式的图片进行转换
/**
 * @param image 图片
 * @param backType 需要返回的类型blob,file
 * @param quality 图片压缩比 0-1,数字越小,图片压缩越小
 * @returns
 */
export default function ImageCompressor(image, backType, quality) {
    return new Promise((resolve, reject) => {
        new Compressor(image, {
            quality: quality || 0.6,
            success(result) {
 
                let file = new File([result], image.name, { type: image.type })
                if (!backType || backType == 'blob') {
                    resolve(result)
                } else if (backType == 'file') {
                    resolve(file)
                } else {
                    resolve(file)
                }
            },
            error(err) {
                console.log('图片压缩失败---->>>>>', err)
                reject(err)
            }
        })
    })
}

3. 非 jpeg 画像を jpeg 画像に変換する ConvertImage.js を作成する

// 思路是创建一个图片,将file等于这个图片,然后创建一个canvas图层 ,将canvas等比例缩放,
//然后用canvas的drawImage将图片与canvas合起来,然后在把canvas的base64转成file即可
export default function ConvertImage(file) {
    return new Promise((resolve, reject) => {
        const fileName = file.name.substring(0, file.name.indexOf('.'));
        let reader = new FileReader(); //读取file
        reader.readAsDataURL(file);
        reader.onloadend = function (e) {
            let image = new Image() //新建一个img标签(还没嵌入DOM节点)
            image.src = e.target.result //将图片的路径设成file路径
            image.onload = function () {
                let canvas = document.createElement('canvas'),
                    context = canvas.getContext('2d'),
                    imageWidth = image.width,    
                    imageHeight = image.height,
                    data = ''
                canvas.width = imageWidth
                canvas.height = imageHeight
 
                context.drawImage(image, 0, 0, imageWidth, imageHeight)
                data = canvas.toDataURL('image/jpeg')
                var newfile = dataURLtoFile(data, fileName + '.jpeg');
                resolve(newfile)
            }
        }
    })
}
function dataURLtoFile(dataurl, filename) { // base64转file对象
    let arr = dataurl.split(','),
        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 });  //转成了jpeg格式
}

3. 画像圧縮ページのコードは次のとおりです。

<template>
	<view class="u-page">
		<view class="u-demo-block">
			<view class="u-demo-block__content">
				<!-- 注意,如果需要兼容微信小程序,最好通过setRules方法设置rules规则 -->
				<u--form
					labelPosition="left"
					:model="form"
					ref="form1"
				>
					<u-form-item
						label="选择照片"
						prop="form.problemDescription"
						borderBottom
						labelWidth="80"
						ref="item3"
					>
	      	<uni-file-picker
			     :source-type="sourceType"
				 :sizeType="sizeType"
		          v-model="fileList1" 
		          mode="grid" 
		          @select="select" 
		          @progress="progress" 
		          @success="success" 
		          @delete ="deletephoto" 
		          @fail="fail"
		       ref="upload"
		       limit="9"
		      />
		     </uni-file-picker>
			 </u-form-item>
			</u--form>
			</view>
		</view>
	</view>
</template>

<script>
	 import { getToken } from "@/utils/auth";
	 import ImageCompressor from "@/utils/imageCompressor"
	 import ConvertImage from "@/utils/ConvertImage"
	 import config from '@/config'
	export default {
		data() {
			return {
				sourceType: ['album', 'camera'],
				sizeType: ['compressed'],
				fileMaxSize: 2 * 1024 * 1024, // 默认最大为2M
				fileMinSize: 50 * 1024, // 最小为50KB
				form: {},
				fileList1: {}, 
				imgSrc:{},
				images: [],
			}
		},
		onReady() {

		},
		mounted() {
		   // this.nowTimes()
		  },
		onLoad(option) {
		
		},
		methods: {
		
				// // 选择上传触发函数
			 async   select(e) {
			    // 根据所选图片的个数,多次调用上传函数
				 this.btndisabled = true;
				 this.loadingflag = true;
				console.log("select")
				console.log(e.tempFilePaths)
			     let promises=[]
				 
			     for (let i = 0; i < e.tempFilePaths.length; i++) {
					
					let imgtemp=e.tempFiles[i].file
					 console.log('img')
					 console.log(e)
					const fileName = imgtemp.name ?? ''
					let url =imgtemp.path
					const fileType = fileName.substring(fileName.indexOf('.') + 1);
					console.log(fileType)
					     // 判断文件是不是jpeg 不是jpeg的都转成jpeg 
					 if (!['jpeg', 'jpg'].includes(fileType)) {
												console.log(fileType)
					        imgtemp = await ConvertImage(imgtemp);  //转陈jpeg格式的file
                    }

					const fileSize = imgtemp.size
					if (fileSize > this.fileMaxSize) {
					const compressionRatio = this.getCompressionRatio(fileSize)
					if (compressionRatio > 1) {
						uni.$u.toast('文件' + fileName + '大于10M')
						return false
					}
				console.log('压缩前文件' + fileName + '==compressionRatio'+compressionRatio+'===大小'+fileSize)
				// #ifdef H5
				   imgtemp = await ImageCompressor(imgtemp, 'blob', compressionRatio); //图片压缩
			     console.log('压缩后文件' + imgtemp.fileName + '====大小'+imgtemp.size)
				 url = window.URL.createObjectURL(imgtemp) 
				// #endif
				 // #ifndef H5
				    this.compressImg(e.tempFilePaths[i],compressionRatio*100,url)
				 // #endif
					}
				  console.log('压缩后文件' + url)
			       const promise =this.uploadFiles(url)
			       promises.push(promise)
				  }
			       Promise.all(promises).then(()=>{
			      })
			   },
			   
			// 图片压缩
			    compressImg(tempFilePath,compressionRatio,url){
			           uni.compressImage({
			             src: tempFilePath,
			              quality: compressionRatio,
			              success: info => {
							  url=info.tempFilePath
			              
			          }
			        })
			    },    
				// 图片压缩比例计算
			  	getCompressionRatio(fileSize) {
			  				const multiple = (fileSize / this.fileMaxSize).toFixed(2) // 获取文件大小倍数,生成质量比
			  				let compressionRatio = 1
			  				if(multiple > 5) {
			  					compressionRatio = 0.5
			  				} else if (multiple > 4) {
			  					compressionRatio = 0.6
			  				} else if (multiple > 3) {
			  					compressionRatio = 0.7
			  				}else if (multiple > 2) {
			  					compressionRatio = 0.8
			  				} else if (multiple > 1) {
			  					compressionRatio = 0.9
			  				} else {
			  					compressionRatio = 2
			  				}
			  					return compressionRatio;
			  	},
			   // 上传函数
			   async uploadFiles(tempFilePath){
				    const baseUrl = config.baseUrl
			      let that =this
			       await uni.uploadFile({
			         url: baseUrl+'/common/upload', //后端用于处理图片并返回图片地址的接口    
			         filePath:tempFilePath,    
			         name: 'file', 
			          header: {
			               Authorization: "Bearer " + getToken(),
			             },
			         success: res => {    
			         let data=JSON.parse(res.data) //返回的是字符串,需要转成对象格式   
			        let imageName=data.fileName				
					 that.images.push(imageName)
					 	console.log(that.images)
					 uni.showToast({ title: '上传成功', icon: "success" });
					   this.btndisabled = false;
					   this.loadingflag = false;
			         },   
			        fail: () => {
			         console.log("上传失败");
					 uni.showToast({ title: '上传失败', icon: "error" });

			        }   
			       })      
			   },
			   // 移出图片函数
			   async deletephoto(){
			    this.fileList1 = {}
			   },

			submit() {
					 
					console.log(this.images)
					this.form.problemPhotos=this.images.join(',');
					addProblems(this.form).then(response => {
					this.$modal.msgSuccess("新增成功");
												  
					})
					}).catch(errors => {
							uni.$u.toast('请扫码,填写问题,上传照片')
					})
			},
           
		}
	}
</script>

(1) 圧縮率の計算

  	getCompressionRatio(fileSize) {
			  				const multiple = (fileSize / this.fileMaxSize).toFixed(2) // 获取文件大小倍数,生成质量比
			  				alert(fileSize+"==="+this.fileMaxSize+"==="+multiple)
			  				let compressionRatio = 1
			  				if(multiple > 5) {
			  					compressionRatio = 0.5
			  				} else if (multiple > 4) {
			  					compressionRatio = 0.6
			  				} else if (multiple > 3) {
			  					compressionRatio = 0.7
			  				}else if (multiple > 2) {
			  					compressionRatio = 0.8
			  				} else if (multiple > 1) {
			  					compressionRatio = 0.9
			  				} else {
			  					compressionRatio = 2
			  				}
			  					return compressionRatio;
			  	},

(2)圧縮

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

(3) H5 圧縮後は blob であり、bloburl に変換する必要があります

uni.uploadFile を使用してファイルをアップロードします。filePath は bloburl のローカル アドレスを使用します。blob :http://localhost:9092/e9a9042b-feab-4fed-99ff-81c1e6efdece

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

})

そのため、圧縮された 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) client_max_body_size 100m を http{} に追加します。ここでは 100M を設定しました。

http { client_max_body_size 100m;     mime.types を含めます。     default_type アプリケーション/オクテット ストリーム;


(3) nginx サービスを再起動します。

おすすめ

転載: blog.csdn.net/zhaolulu916/article/details/129691562
おすすめ