您的位置:首页 > Web前端 > HTML5

HTML5 本地裁剪图片并上传至服务器(老梗)

2015-01-04 12:54 295 查看
很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的。但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 5 步。步骤繁琐不说,当很多用户上传图片的时候也很影响服务器性能。

HTML5 的出现让我们可以更方便的实现这一需求。虽然这里所说的技术都貌似有点过时了(前端界的“过时”,你懂的),但还是有些许参考价值。在这里我只说一下要点,具体实现同学们慢慢研究。

下面奉上我自己写的一个demo,在输入框中选好自己服务器 url, 生成好图片后点击 Submit 上传,然后自己去服务器里看看效果吧~~

浏览器要求支持以下 Feature:

File API

Blob

atob

canvas

代码直接从现有项目移植过来,没有经过“太多的”测试,写的很乱,也没注释,大家就慢慢看吧。。。重点就在 js 脚本的 28 行,
clipImage
函数中,同学们可以直接跳过去看。

http://jsfiddle.net/windwhinny/d5qan0q7/

第一步:获取文件

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

javascript
$('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
里,这样本地图片就显示出来了。

javascript
$('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 上有详细的说明。

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


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

javascript
// 以下四个参数由第三步获得
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
转换一下。总之这里挺麻烦的。。

javascript
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
里请求。

javascript
var fd=new FormData();

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

然后你服务器里应该就可以收到这个文件了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: