PHP群:95885625 Hbuilder+MUI群:81989597 站长QQ:634381967
    您现在的位置: 首页 > 开发编程 > HTML5+CSS3教程 > 正文

    HTML5裁剪图片并上传至服务器实现原理讲解

    作者:admin来源:segmentfault浏览:时间:2020-09-30 00:07:50我要评论
    导读:经常做项目需要本地上传图片裁剪并上传服务器,比如会议头像等功能,但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回...
    经常做项目需要本地上传图片裁剪并上传服务器,比如会议头像等功能,但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 5 步。步骤繁琐不说,当很多用户上传图片的时候也很影响服务器性能。

    第一步:获取文件

    HTML5 支持从 input[type=file] 元素中直接获取文件信息,也可以读取文件内容。我们用下面代码就可以实现:

    $('input[type=file]').change(function(){
        var file=this.files[0];
        // continue ...
    });
    

    第二部:读取文件,并生成 Image 元素

    这一步就需要用到 FileReader 了,这个类是专门用来读取本地文件的。纯文本或者二进制都可以读取,但是本地文件必须是经过用户允许才能读取,也就是说用户要在input[type=file]中选择了这个文件,你才能读取到它。

    通过 FileReader 我们可以将图片文件转化成 DataURL,就是以 data:image/png;base64, 开头的一种URL,然后可以直接放在 image.src 里,这样本地图片就显示出来了。

    $('input[type=file]').change(function(){
        var file=this.files[0];
    
        var reader=new FileReader();
        reader.onload=function(){
            // 通过 reader.result 来访问生成的 DataURL
            var url=reader.result;
            setImageURL(url);
        };
        reader.readAsDataURL(file);
    });
    
    var image=new Image();
    function setImageURL(url){
        image.src=url;
    }
    

    Image 就是在 html 里的 <img> 标签,所以可以直接插入到文档流里。

    第三步:获取裁剪坐标

    这一步没啥好说的,实现的方法也很多,需要获得下面四个裁剪框的坐标:

    • Y坐标
    • X坐标
    • 高度
    • 宽度

    如下图所示:
    HTML5裁剪图片并上传至服务器实现原理讲解

    第四部:裁剪图片

    这是时候我们就需要用到 canvas 了,canvas 和图片一样,所以新建 canvas 时就要确定其高宽。这里我们还运用到image.naturalHeight 和 image.naturalWidth 这两个属性来获取图片原始尺寸。

    将图片放置入 canvas 时需要调用 drawImage ,这个接口参数比较多,在 MDN 上有详细的说明。

    drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
    

    HTML5裁剪图片并上传至服务器实现原理讲解

    因为我们用 canvas 只是用于裁剪图片的,所以需要新建一个 canvas 让它的尺寸和裁剪之后图片的尺寸相等,此时canvas 就相当与我们的裁剪框。运用这个函数还可以将大图缩放成小图,同学们自己研究吧。

    // 以下四个参数由第三步获得
    var x,  
        y,
        width,
        height;
    
    var canvas=$('<canvas width="'+width+'" height="'+height+'"></canvas>')[0],
        ctx=canvas.getContext('2d');
    
    ctx.drawImage(image,x,y,width,height,0,0,width,height);
    $(document.body).append(canvas);
    

    将 canvas 加入文档流之后,就可以看到裁剪后的效果了。不过我们还需要将图片上传至服务器里。

    第五步:读取裁剪后的图片并上传

    这时我们要获取 canvas 中图片的信息,用 toDataURL 就可以转换成上面用到的 DataURL 。 然后取出其中 base64 信息,再用 window.atob 转换成由二进制字符串。但 window.atob 转换后的结果仍然是字符串,直接给 Blob 还是会出错。所以又要用 Uint8Array 转换一下。总之这里挺麻烦的。。

    var data=canvas.toDataURL();
    
    // dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
    data=data.split(',')[1];
    data=window.atob(data);
    var ia = new Uint8Array(data.length);
    for (var i = 0; i < data.length; i++) {
        ia[i] = data.charCodeAt(i);
    };
    
    // canvas.toDataURL 返回的默认格式就是 image/png
    var blob=new Blob([ia], {type:"image/png"});
    

    这时候裁剪后的文件就储存在 blob 里了,我们可以把它当作是普通文件一样,加入到 FormData 里,并上传至服务器了。

    FormData 顾名思义,就是用来创建表单数据的,用 append 以键值的形式将数据加入进去即可。但他最大的特点就是可以手工添加文件或者 Blob 类型的数据,Blob 数据也会被当作文件来处理。原生 js 可以直接传递给 xhr.send(fd), jquery 可以放入 data 里请求。

    var fd=new FormData();
    
    fd.append('file',blob);
    $.ajax({
        url:"your.server.com",
        type:"POST",
        data:fd,
        success:function(){}
    });
    

    然后你服务器里应该就可以收到这个文件了~

    转载请注明(B5教程网)原文链接:https://b5.mxunkeji.com/content-142-3007-1.html
    相关热词搜索: