💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] * * * * * ### 一、图片上传的思路 1. 获取上传的图片,可以是通过 `<input type='file'>` 获取的也可以是通过拖放上传的图片 2. 通过canvas处理(压缩,旋转)图片 3. 将canvas处理后的图片转化为二进制 4. 通过`FormData() API`生成formdata 对象上传服务器 如果了解下边的api 则更加容易 - [ArrayBuffer处理二进制](https://www.kancloud.cn/webxiaoma/javascript/708943) - [Blob处理类文件对象](https://www.kancloud.cn/webxiaoma/javascript/706859) - [FileReader和FormData对象](https://www.kancloud.cn/webxiaoma/javascript/708944) - [base64处理](https://www.kancloud.cn/webxiaoma/javascript/709983) ### 二、图片上传的实现 现在我们来编写处理上传图片的函数 `createImg` ```JavaScript function createImg(file){ // 处理上传图片的函数 let reader = new FileReader(); reader.readAsDataURL(file); // 将接收到的图片以DataUrl格式读取为 reader.onload=() => { // 文件读取成功执行 let url = reader.result; let image = new Image() image.src = url; image.onload = ()=>{ // 图片加载成功后执行 let canvasImg = document.createElement('canvas'); canvasImg.width = image.width canvasImg.height = image.height let ctx = canvasImg.getContext("2d") ctx.drawImage(image, 0, 0,image.width,image.height); let dataURL = canvasImg.toDataURL("image/jpeg",0.8); // 将canvas 转化为base64格式,并将canvas压缩0.8 let byteURL = atob(dataURL.split(',')[1]) // 解码base64 // 获取图片类型 let mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]; // 将canvas 转为字节流 let buffer = new ArrayBuffer(byteURL.length); let uintAry = new Uint8Array(buffer); //转化为8位无符号整数,长度1个字节 for (var i = 0; i < byteURL.length; i++) { uintAry[i] = byteURL.charCodeAt(i); // charCodeAt() 方法可返回指定位置的字符的 Unicode 编码 } let blob = new Blob([buffer],{type: mimeString}) let fd = new FormData(); fd.append("file", blob); return fd; } } } ``` 接下来我们就需要上传图片了,有两种上传图片的方式,上面我们也提了 1. 通过input上传 ```HTML <input id="file" type="file" accept="image/*" > <script> let inp = document.getElementById('file') inp.onchange = function(e){ let file = e.target.files[0] createImg(file) // 上边处理图片的函数 } </script> ``` 2. 拖动上传 ```HTML <div id="uploadImg"> 将图片拖拽到此区域 </div> <img alt="拖动显示的图片"/> <script> let imgWrap = document.getElementById('uploadImg') let img = document.querySelector('img') imgWrap.ondragover = function(e){ // 拖动到放置框时触发(持续触发) e.preventDefault(); } imgWrap.ondrop = function(e){ // 进行放置时触发 e.preventDefault(); let files = e.dataTransfer.files let fileType = files[0].type if(!/^image\/(jpeg|png)/.test(fileType)){ console.log("上传的不是图片") return false } let url = URL.createObjectURL(files[0]) // 生成Blob URL 展示缩略图 img.src = url createImg(files) // 上边处理图片的函数 } </script> ``` ### 三、图片上传的一些注意点 #### 1. 调用手机相册或照相机 在移动端时调用手机相册我们可以使用 ```HTML <input type="file" accept="image/*" > ``` 在移动端时调用手机相机我们可以使用 ```HTML <input type="file" accept="image/*" capture="camera"> ``` #### 2. 苹果手机拍照后,上传的图片旋转了 这里是因为ios手机拍照时默认横屏拍照是0度,竖屏拍照图片会旋转90度,这里我们可以使用 [exif-js](https://github.com/exif-js/exif-js) [推荐阅读](https://moxo.io/blog/2017/03/21/using-javascript-to-read-orientation-value-inside-jpeg-file/) ```JavaScript import EXIF from 'exif-js' let inp = document.getElementById('file') inp.onchange = function(e){ let file = e.target.files[0] EXIF.getData(file, function() { let Orientation = EXIF.getTag(this, 'Orientation'); let roate; if(Orientation != "" && Orientation != 1){ switch(Orientation){ case 6://需要顺时针(向左)90度旋转 roate = 90 break; case 8://需要逆时针(向右)90度旋转 roate = -90 break; case 3://需要180度旋转 roate = 180 break; } } createImg(file,roate) // 上边处理图片的函数 }); } ```