使用antd-mobile ImagePicker组件 七牛上传图片(排坑)

 

项目需要一个添加多张图片再把图片url传给后台的组件(嘛,照片选取用ImagePicker就好啦)大体样子如下

主要问题是在使用七牛取到url之后的存取问题

下面主要讨论使用ImagePicker换行时browse_button对应id出现的问题。另外说一下移动端如何让id对应按钮直接调起相机以及图片压缩的方法。(使用七牛js版本为1.x,静态文件方式引入,antd-mobile使用2.x)

七牛官方文档     plupload使用指南

解决id问题

componentDidMount(){
    let _this = this;
    let imgBox = document.getElementsByClassName(this.props.name);
    imgBox[0].getElementsByTagName("input")[0].setAttribute('id',this.props.inputID);
    imgBox[0].getElementsByTagName("input")[0].addEventListener('onporpertychange',this.onChange);
    var Qiniu1 = new QiniuJsSDK();
    var commonOption={
        runtimes: 'html5,flash,html4',      // 上传模式,依次退化
        uptoken_url: baseURL+'free/getQiNiuToken',    // Ajax 请求 uptoken 的 Url,**强烈建议设置**(服务端提供)
        get_new_uptoken: false,             // 设置上传文件的时候是否每次都重新获取新的 uptoken
        unique_names: true,              // 默认 false,key 为文件名。若开启该选项,JS-SDK 会为每个文件自动生成key(文件名)
        domain: 'image.xxxxxx.com',     // bucket 域名,下载资源时用到,如:'http://xxx.bkt.clouddn.com/' **必需**
        auto_start: true                   // 选择文件后自动上传,若关闭需要自己绑定事件触发上传,
    }
    var init1={
        init:{
            'FilesAdded': function (up, files) {
                // 设置预览图地址
            },
            'FileUploaded': function (up, file, info) {
                var domain = up.getOption('domain');
                var res = JSON.parse(info);
                var sourceLink = "http://"+domain+"/"+res.key;//目标地址
                console.info(sourceLink);
                _this.props.saveImg(_this.props.name,sourceLink)
            },
            'Error': function(up, err, errTip) {
                //上传出错时,处理相关的事情
                console.log(err);
            },
            'Key': function (up, file) {
                var key = "";
                return key
            }
        }
    }
    var aimId1={browse_button: this.props.inputID};
    var option1 = Object.assign(commonOption, init1,aimId1);
    var uploader1 = Qiniu1.uploader(option1);
}

看起来是没有问题,给input标签一个id,通过此id上传、获取七牛返回的地址再进行显示,但实际情况会出现两个问题

1.换行后图片上传失败   

 2.ImagePicker限制图片张数(不显示添加按钮)添加最后一张后删除任一张图片再进行上传失效

先找找原因

    imgBox[0].getElementsByTagName("input")[0].setAttribute('id',this.props.inputID);

如果你看过imagepicker里添加按钮的input标签后,你会发现在每次添加图片后此id会保留(即每次添加图片这个按钮会往后移一位),当然有两种情况会重新生成input标签(1换行2删掉最后一张照片)这两种情况下input标签下没有id,昂这个简单把componentDidMount换成componentDidUpdate是不是就行了(不行哦会有问题)

换行后

那好,针对这两种情况做下处理

        let imgBox = document.getElementsByClassName(this.props.name);
        let num = imgBox[0].getElementsByClassName('am-image-picker-list')[0].childNodes.length;
        if(this.state.rowNum !== num){   //用于判断第一种情况
            this.setState({rowNum:num});
            this.onLoadImg();
        }
        else if (this.state.isLastPosition){  //用于判断第二种情况
            this.onLoadImg();
        }

解决后的代码:

export default class extends React.Component{
    constructor(props){
        super(props);
        this.state={
            rowNum:1,
            isLastPosition:false,//如果是已上传到最后一张再删除会因为input没赋id导致无法上传七牛
        };
    }

    componentDidMount(){
        this.onLoadImg();
    }

    componentDidUpdate(){
        let imgBox = document.getElementsByClassName(this.props.name);
        let num = imgBox[0].getElementsByClassName('am-image-picker-list')[0].childNodes.length; //获取行数
        if(this.state.rowNum !== num){
            this.setState({rowNum:num});
            this.onLoadImg();
        }
        else if (this.state.isLastPosition){
            this.onLoadImg();
        }
    }

    onLoadImg =()=>{
        let _this = this;
        let imgBox = document.getElementsByClassName(this.props.name);
        console.log(imgBox[0]);
        if(imgBox[0].getElementsByTagName("input")[0] !==undefined){
            imgBox[0].getElementsByTagName("input")[0].setAttribute('id',`${_this.props.inputID}`);
            imgBox[0].getElementsByTagName("input")[0].addEventListener('onporpertychange',this.onChange);
            var Qiniu = new QiniuJsSDK();
            var commonOption={
                runtimes: 'html5,flash,html4',      // 上传模式,依次退化
                uptoken_url: baseURL+'free/getQiNiuToken',    // Ajax 请求 uptoken 的 Url,**强烈建议设置**(服务端提供)
                get_new_uptoken: false,             // 设置上传文件的时候是否每次都重新获取新的 uptoken
                unique_names: true,              // 默认 false,key 为文件名。若开启该选项,JS-SDK 会为每个文件自动生成key(文件名)
                domain: 'image.quantahelp.com',     // bucket 域名,下载资源时用到,如:'http://xxx.bkt.clouddn.com/' **必需**
                auto_start: true                   // 选择文件后自动上传,若关闭需要自己绑定事件触发上传,
            }
            var init={
                init:{
                    'FilesAdded': function (up, files) {
                        // 设置预览图地址
                    },
                    'FileUploaded': function (up, file, info) {
                        var domain = up.getOption('domain');
                        var res = JSON.parse(info);
                        var sourceLink = "http://"+domain+"/"+res.key;//目标地址
                        console.info(sourceLink);
                        _this.props.saveImg(_this.props.name,sourceLink)
                    },
                    'Error': function(up, err, errTip) {
                        //上传出错时,处理相关的事情
                        console.log(err);
                    },
                    'Key': function (up, file) {
                        var key = "";
                        return key
                    }
                }
            };
            var aimId={browse_button: `${_this.props.inputID}`};
            var option = Object.assign(commonOption, init,aimId);
            var uploader = Qiniu.uploader(option);
        }
    };

    onChange =key=> (files, type, index) => {
        if(type=='remove'){ //删除图片
            this.props.removeImg(key,files,index)
        }
    };

    onDeleteChange =key=> (files, type, index) => {
        if(type=='remove'){ //删除图片
            this.props.removeImg(key,files,index);
            console.log(this.props.files.length);
            if (files.length ===this.props.num-1){
                // this.isLastPosition =true
                this.setState({isLastPosition:true})
            }else {
                this.setState({isLastPosition:false})
            }
        }else {
            this.setState({isLastPosition:false})
        }
    };
    render(){
        // this.isLastPosition =false;
        const { files } = this.props;
        return(
            <ImagePicker files={files} onChange={this.onDeleteChange(this.props.name)} selectable={files.length < this.props.num} className={this.props.name}/>
        )
    }
}

直接调起相机

在说怎么调起相机之前,先了解一下七牛如何通过给browse_button一个id或元素就使其调起照片选择的。这里先给任意标签一个id='idImg1',让browse_button使用此id。看下网页生成的布局

这样看就清楚了,当我们对应id后,会在当前标签所在层级最后生成一个div标签覆盖在id对应的标签上并且此标签子元素是一个input,通过此来调起照片选择。那么想要调起相机只需要更改input中部分属性即可。代码如下

这里还要注意这个标签的生成时间,我是在componentDidMount中执行七牛的方法但这个div标签生成却是在此周期执行完后,所以要想通过下面代码修改真实DOM就一定要确保此标签以生成。(我是通过在DidMount中使用setTimeout延时2s再执行代码来解决的,因为实在找不到监听此标签生成的办法。_(:3」∠))

        let camera = document.getElementById('idImg1');
        if (camera.nextSibling.nextSibling){
            camera.nextSibling.nextSibling.firstChild.setAttribute('capture','camera');
            camera.nextSibling.nextSibling.firstChild.setAttribute('accept','image/*');
            camera.nextSibling.nextSibling.firstChild.removeAttribute('multiple')
        }

 图片压缩

这个建议参考一下此文章

在commonOption中添加此属性即可是实现图片压缩

resize: {
crop: true,
quality: 60,
preserve_headers: false
}

完整代码 这里 (token获取方式请自己添加,此项目并未引入七牛库,请在自己项目中测试)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
Ant Design Mobileantd-mobile)并没有提供上传视频的组件,但是可以使用 Ant Design 的 `Upload` 组件来实现上传视频的功能。具体步骤如下: 1. 安装 Ant Design 和 Ant Design Mobile: ```bash npm install antd antd-mobile --save ``` 2. 在需要使用上传组件的页面引入 `Upload` 组件和 `Button` 组件: ```jsx import { Upload, Button } from 'antd'; ``` 3. 在页面中添加 `Upload` 组件: ```jsx <Upload> <Button>上传视频</Button> </Upload> ``` 4. 在 `Upload` 组件中添加上传视频的逻辑。可以使用 `beforeUpload` 方法来验证上传的文件格式和大小,并使用 `customRequest` 方法将视频上传到服务器。 ```jsx <Upload beforeUpload={this.beforeUpload} customRequest={this.uploadVideo} > <Button>上传视频</Button> </Upload> ``` 其中,`beforeUpload` 方法的实现可以参考下面的代码: ```jsx // 验证上传的文件格式和大小 beforeUpload = (file) => { const isVideo = file.type === 'video/mp4'; if (!isVideo) { message.error('只能上传 MP4 格式的视频!'); } const isLt100M = file.size / 1024 / 1024 < 100; if (!isLt100M) { message.error('视频大小不能超过 100MB!'); } return isVideo && isLt100M; } ``` `uploadVideo` 方法的实现可以参考下面的代码: ```jsx // 将视频上传到服务器 uploadVideo = (options) => { const { file, onSuccess, onError } = options; const formData = new FormData(); formData.append('video', file); // 发送 POST 请求上传视频 axios.post('/api/uploadVideo', formData).then((response) => { onSuccess(response.data, file); }).catch((error) => { onError(error); }); } ``` 完整代码实现如下: ```jsx import React from 'react'; import { Upload, Button, message } from 'antd'; import axios from 'axios'; class UploadVideo extends React.Component { // 验证上传的文件格式和大小 beforeUpload = (file) => { const isVideo = file.type === 'video/mp4'; if (!isVideo) { message.error('只能上传 MP4 格式的视频!'); } const isLt100M = file.size / 1024 / 1024 < 100; if (!isLt100M) { message.error('视频大小不能超过 100MB!'); } return isVideo && isLt100M; } // 将视频上传到服务器 uploadVideo = (options) => { const { file, onSuccess, onError } = options; const formData = new FormData(); formData.append('video', file); // 发送 POST 请求上传视频 axios.post('/api/uploadVideo', formData).then((response) => { onSuccess(response.data, file); }).catch((error) => { onError(error); }); } render() { return ( <Upload beforeUpload={this.beforeUpload} customRequest={this.uploadVideo} > <Button>上传视频</Button> </Upload> ); } } export default UploadVideo; ``` 需要注意的是,上传视频的具体实现要根据后端 API 的要求来进行调整。以上代码仅供参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值