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

 
经常做项目需要本地上传图片裁剪并上传服务器,比如会议头像等功能,但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 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坐标
  • 高度
  • 宽度

如下图所示:

第四部:裁剪图片

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

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

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

因为我们用 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(){}
});

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

HTML5裁剪图片并上传至服务器实现原理讲解的更多相关文章

  1. HTML5 本地裁剪图片并上传至服务器(转)

    很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的.但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 ...

  2. 小程序踩坑记录-上传图片及canvas裁剪图片后上传至服务器

    最近在写微信小程序的上传图片功能,趟过了一些坑记录一下. 想要满足的需求是,从手机端上传图片至服务器,为了避免图片过大影响传输效率,需要把图片裁剪至适当大小后再传输 主要思路是,通过wx.choose ...

  3. 导出HTML5 Canvas图片并上传服务器功能

    这篇文章主要介绍了导出HTML5 Canvas图片并上传服务器功能,文中通过实例代码给大家介绍了HTML5 Canvas转化成图片后上传服务器,代码简单易懂非常不错,具有一定的参考借鉴价值,需要的朋友 ...

  4. HTML5 Canvas前台压缩图片并上传到服务器

    1.前台代码: <input id="fileOne" type="file" /> <input id="btnOne" ...

  5. 深入研究HTML5实现图片压缩上传

    上篇文章中提到移动端上传图片,我们知道现在流量还是挺贵的,手机的像素是越来越高,拍个照动不动就是好几M,伤不起.虽然客户端可以轻轻松松实现图片压缩再上传,但是我们的应用还可能在浏览器里面打开,怎么办呢 ...

  6. js实现图片粘贴上传到服务器并展示

    最近看了一些有关于js实现图片粘贴上传的demo,实现如下: (这里只能检测到截图粘贴和图片右键复制之后粘贴) demo1: document.addEventListener('paste', fu ...

  7. base64字符串转文件,以及ngImgCrop裁剪图片并上传保存到服务器示例

    base64字符串是包含文件格式的文件字符串,例如:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAgAElE ...

  8. PHP裁剪图片并上传完整demo

    日前根据功能需求,要做一个图片裁剪上传的功能,在网上找了好久,找到了这位仁兄写的demo! 下载压缩包

  9. 基于HTML5多图片Ajax上传可预览

    html5多图控件<input id="fileImage" type="file" size="30" name="fil ...

随机推荐

  1. rc-local.service服务启动失败,导致rc.local中的开机启动服务不能启动

    chmod  +x   /etc/rc.d/rc.local 打开/etc/rc.local文件,将启动非后台执行的指令的最后添加 &,以使相关指令后台运行,然后启动服务 systemctl  ...

  2. validate 常用的输入框校验

    记录一下angular可以直接用的输入框校验器,外加一个国内手机号码的校验 <!DOCTYPE html> <html> <head> <meta chars ...

  3. C语言学习13

    快速排序 //快速排序 #include <stdio.h> void quicksort(int a[], int left, int right); void main() { ] = ...

  4. 记第一次面试的悲惨经历QAQ

    面试岗位:测试开发 自我介绍 :根据介绍的内容,会问简历上涉及到的东西,主要是项目: 手写代码:给一个数组,求数组中所有数字拼接后能得到的最小数字.例:{3,32,312},输出312323. 关于计 ...

  5. POJ 2485 Highways (求最小生成树中最大的边)

    Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public h ...

  6. POJ 1383 Labyrinth (树的直径求两点间最大距离)

    Description The northern part of the Pyramid contains a very large and complicated labyrinth. The la ...

  7. 初次使用xUtils3

    由于初学Android,之前也没接触过xUtils2.X系列,所以xUtils3.X弄了很久还是一直报空指针异常,后来看了Sample找到问题所在,现在把xUtils3.X的使用写来供像我这样的小白参 ...

  8. BootStrap学习02栅格系统

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 局部二值模式(Local Binary Patterns)纹理灰度与旋转不变性

    Multiresolution Gray Scale and Rotation Invariant Texture Classification with Local Binary Patterns, ...

  10. HDU 4418 高斯消元解决概率期望

    题目大意: 一个人在n长的路径上走到底再往回,走i步停下来的概率为Pi , 求从起点开始到自己所希望的终点所走步数的数学期望 因为每个位置都跟后m个位置的数学期望有关 E[i] = sigma((E[ ...