解决HTML5IOS拍照上传图片逆时针旋转90度问题,React

一般情况下是 是使用 Exif.js 来读取图像的元数据 orientation(方向)

但是这里使用了antd-mobile 的ImagePicker 组件, onChange 函数直接返回了orientation参数,所以不需要使用exif.js了

1. 获取orientation参数和文件参数

    onChange = (files, type) => {
        if(type === 'add'){
            this.setState({
                loading:true,
                orientation:files[0].orientation
            })
            this.transformBase64(files[0].file)
        }else {
            this.setState({loading:true})
            this._Upload(this.state.index,'')
        }
    }

2.转换base64

    //转换base64
    transformBase64 (file){
        const self = this;
        const reader = new FileReader();
        reader.readAsDataURL(file);
        /* eslint-disable func-names */
    // 箭头函数会改变this,所以这里不能用肩头函数
        reader.onloadend = function () {
            // this.result就是转化后的结果
            const result = this.result;
            // 将base64添加到图片标签上
            const img = new Image();
            img.src = result;
            img.onload = function () {
                // 获取旋转后的图片
                const data = self.getRotateImg(img,self.state.orientation);
                // 如果上传接口不支持base64,则这里需要将base64转为文档流
                const file = self.dataURLtoFile(data);
                // 调用接口,上传图片
                self.transformFileToFormData(file)
            }
        };
    }

3.将File append进 FormData

// 将File append进 FormData
    transformFileToFormData (file) {
            const formData = new FormData();
        // 自定义formData中的内容
        // type
        formData.append('type', file.type);
        // size
        formData.append('size', file.size || "image/jpeg");
        // name
        formData.append('name', file.name);
        // lastModifiedDate
        formData.append('lastModifiedDate', file.lastModifiedDate);
        // append 文件
        formData.append('file', file);
        // 上传图片
        this.uploadImg(formData);
    }

4.获取图片返回地址

    uploadImg  = (formData) => {
        const xhr = new XMLHttpRequest();

        // 进度监听
        // xhr.upload.addEventListener('progress', (e)=>{console.log(e.loaded / e.total)}, false);
        // 加载监听
        // xhr.addEventListener('load', ()=>{console.log("加载中");}, false);
        // 错误监听
        xhr.addEventListener('error', ()=>{
            const step =  this.state.index;
            this.setState({
                modeling:false
            });
            if(step === 1){
                this.setState({
                    faced:[]
                })
            }else if(step === 2){
                this.setState({
                    lookUp:[]
                })
            }else if(step === 3){
                this.setState({
                    overLook:[]
                })
            }else if(step === 4){
                this.setState({
                    left:[]
                })
            }else if(step === 5){
                this.setState({
                    right:[]
                })
            }
            Toast.fail('建模失败', 1)
        }, false);
        xhr.onreadystatechange =  () => {
            if (xhr.readyState === 4) {
                    if(xhr.status === 200 ){
                        const result = JSON.parse(xhr.responseText);
                        if (result.status === 10000) {
                            this._Upload(this.state.index,`http:${result.url}`,result.filename)
                            this.setState({
                                faced:[{
                                    url:`http:${result.url}`,
                                    id:123
                                }]
                            })
                        } else {
                            const step =  this.state.index;
                            this.setState({
                                modeling:false
                            });
                            if(step === 1){
                                this.setState({
                                    faced:[]
                                })
                            }else if(step === 2){
                                this.setState({
                                    lookUp:[]
                                })
                            }else if(step === 3){
                                this.setState({
                                    overLook:[]
                                })
                            }else if(step === 4){
                                this.setState({
                                    left:[]
                                })
                            }else if(step === 5){
                                this.setState({
                                    right:[]
                                })
                            }
                            Toast.fail(result.message,1.5)
                        }
                    }else {
                        const step =  this.state.index;
                        this.setState({
                            modeling:false
                        });
                        if(step === 1){
                            this.setState({
                                faced:[]
                            })
                        }else if(step === 2){
                            this.setState({
                                lookUp:[]
                            })
                        }else if(step === 3){
                            this.setState({
                                overLook:[]
                            })
                        }else if(step === 4){
                            this.setState({
                                left:[]
                            })
                        }else if(step === 5){
                            this.setState({
                                right:[]
                            })
                        }
                        Toast.fail('建模失败', 1)
                    }
            }
        };
        xhr.open('POST', '/api/file/file/upload' , true);
        xhr.send(formData);
    };

5.上传图片

    _Upload = (status,src,filename) => {
        this.setState({
            loading:true
        })
        this.tag = 'faced_id_card'
        if(status === 1){
            this.tag = "faced_id_card"
        }else if(status === 2){
            this.tag = "back_id_card"
        }

        HttpUtils.postForm('/api/face/image/save', {
            tag:this.tag,
            scheme:'http:',
            category:2,
            filename
        }).then(res => {
            this.setState({
                loading:false
            })
            if (res.status === 10000) {
               if(src === ''){
                   Toast.info('删除成功',1)
                   if(status === 1 ){
                       this.setState({
                           haveAvatar:[]
                       })
                   }else if(status === 2 ){
                       this.setState({
                           haveNationalEmblem:[]
                       })
                   }
               }else {
                   Toast.info('上传成功',1)
                   if(this.state.status === 1 ){
                       this.setState({
                           haveAvatar:[{
                               url:src,
                               id:Number((Math.random()*10000).toFixed(0))
                           }],
                       })
                   }else if(this.state.status === 2 ){
                       this.setState({
                           haveNationalEmblem:[{
                               url:src,
                               id:Number((Math.random()*10000).toFixed(0))
                           }],
                       })
                   }
               }
            } else {
                Toast.fail(res.message,1.5)
            }
        }).catch(err => {
            Toast.info('操作失败',1.5)
            this.setState({
                loading:false
            });
        })
    }

后续:

遇到的问题

IphoeXS / iphone 6S / iphone7 在未处理的情况下都是逆时针90度 获取的Orientation为6

iphone XR / iphone 11 在未处理的情况下是正常的 获取的Orientation 也是6

找到原因

解决办法:

        let userAgent= navigator.userAgent.toLowerCase();
        let ios=userAgent.match(/cpu iphone os (.*?) like mac os/);
        let reg = /.*\..*/;  //判断是否有小数点
        if(!ios){
            //正常
        }else{
            let iosVersion = ios[1].replace(/_/g,"."); //获取ios系统版本
            if(Number(iosVersion.split('.')[0]) < 13){
                //转
            }else {
                if(Number(iosVersion.split('.')[0]) > 13){
                    //正常
                }else {
                    //等于13 判断ios系统有无.
                    if(reg.test(iosVersion)){
                        if(Number(iosVersion.split('.')[1]) < 4){
                            //转
                        }else {
                            //正常
                        }
                    }else {
                        //转
                    }
                }
            }
        }

附加:react 使用exif的办法

yarn add exif-js

   import {EXIF} from 'exif-js';   
let self = this EXIF.getData(files[0].file, function() { //alert(EXIF.getTag(this, 'Orientation')); console.log("this",JSON.stringify(EXIF.getTag(this, 'Orientation'))) console.log('让我康康or',EXIF.getTag(this, 'Orientation')) // return self.setState({ or2:JSON.stringify(this.exifdata) }) });