视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
如何使用H5做出上传图片功能
2020-11-27 15:05:35 责编:小采
文档
这次给大家带来如何使用H5做出上传图片功能,如何H5做出上传图片功能的注意事项有哪些,下面就是实战案例,一起来看一下。

前几日做了项目,其中有一个模块涉及到上传图片至服务器。今天抽空整理了下,发现越整理涉及的知识点越多,下面例子有参考百度的搜图。

知识点:input file、base、FileReader、canvas压缩、blob、btoa编码和atob解码、FormData。

html dom节点:

<input type="file">

默认可以选择一个文件。需要上传多张。可以增加multiple="true" 属性。一般使用opacity:0;将默认样式隐藏,然后再重新写其样式。

1、创建对象

var fileReader = new FileReader();

2、判断浏览器是否兼容----ie8下不支持

if( window.FileReader )

3、状态常量

常量名描述
EMPTY0为开始读取文件
LOADING1文件读取中
DONE2文件读取完成

在下面例子中,可以分别读取当前状态。

4、属性

属性名描述
error读取文件时发生错误
readyState当前fileReader对象的状态,为上述状态常量的一个
result读取到的内容

5、方法

方法名参数描述
abort中止读取,在非LOADING状态时调用会抛出异常
readAsArrayBufferblob/file读取为数组,在result中有一个ArrayBuffer对象为读取的内容
readAsBinaryStringblob/file读取为二进制,在result中有读取文件的原始二进制
readAsDataUrlblob/file读取为dataUrl,在result中有data:url格式的字符串表示读取的内容
readAsTexxblob/file , [encoding]读取为文本,在result中字符串表示读取的内容

6、事件处理

事件描述
onabort中断时触发
onerror出错时触发
onload读取成功时触发
onloadend读取完成时触发(不论成功是否)
onloadstart读取开始时触发
onprocess读取中触发

BASE:

我们用chrome打开一张图片,在resources里面显示的就是图片的base编码(实际上base编码比原图片稍大)

图片的base编码也就是将一张图片编码成一个字符串,我们可以用这个字符串给img标签的src赋值,这样我们就可以看到这张图片。

如何编写:

在html中:

<img src="data:image/gif;base,R0lGODlhAwADAIABAL6+vv///yH5BAEAAAEALAAAAAADAAMAAAIDjA9WADs=">

在css中:

background-image:url(data:image/gif;base,R0lGODlhBAABAIABAMLBwfLx8SH5BAEAAAEALAAAAAAEAAEAAAICRF4AOw==);

优缺点:

优点:1、减少了http请求;2、可以被gzip;3、没有跨域问题;4、无需考虑在更新图片时缓存问题。

缺点:1、ie8以下不支持;2、不论是写在css文件还是html文件中,增加了文件的大小;3、图片大了之后,程序员编码相当困难;

应用:

根据实际需求来选择base显示图片,或者选择css sprite,或者直接使用png等

一般使用场景:很少被更新,实际尺寸很小,在系统中大量使用。

canvas压缩:

在移动应用场景中,用户上传的图片一般很大,会导致上传时间过长而失败,既浪费时间也浪费流量,更影响用户体验。我们可以使用canvas的drawImage方法的图形裁剪功能。

1、新建image对象,给其src复制base值,在其监听onload事件;

2、在onload事件方法中新建canvas对象,获取上下文context;

3、设置裁剪比例,调用drawImage方法填充图片。

4、通过toDataUrl方法获取裁剪之后的base值。

详细见下例。

Blob

在传输一些比较大的图片的base是容易出现转发错误,这里我们可以将base转换成blob字段写到form表单中提交到后台。一般blob和base之间的相互转换通过fileReader 的readAsDataUrl和ArrayBuffer的charCodeAt方法。下面列举几个相互转换的方法。来自(http://jsperf.com/blob-base-conversion)

 var blobToBase = function(blob, cb) {
var reader = new FileReader();
reader.onload = function() {
var dataUrl = reader.result;
var base = dataUrl.split(',')[1];
cb(base);
};
reader.readAsDataURL(blob);
};
var baseToBlob = function(base, cb) {
var binary = atob(base);
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
cb(new Blob([view]));
};
var baseToBlobSync = function(base) {
var binary = atob(base);
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
var blob = new Blob([view]);
return blob;
};
var blobToBase_2 = function(blob, cb) {
var reader = new FileReader();
reader.onload = function() {
var buffer = reader.result;
var view = new Uint8Array(buffer);
var binary = String.fromCharCode.apply(window, view);
var base = btoa(binary);
cb(base);
};
reader.readAsArrayBuffer(blob);
};

btoa 与 atob: ---在对base转blob时就需要用atob对base进行解码

btoa("javascript"); //"amF2YXNjcmlwdA=="
atob("amF2YXNjcmlwdA==") ; //"javascript"

注意:在需要转码中文时,需要用encodeURIComponent方法对中文处理,解码时用decodeURIComponent

btoa(encodeURIComponent("我喜欢 javascript")); //"JUU2JTg4JTkxJUU1JTk2JTlDJUU2JUFDJUEyJTIwamF2YXNjcmlwdA=="
decodeURIComponent(atob("JUU2JTg4JTkxJUU1JTk2JTlDJUU2JUFDJUEyJTIwamF2YXNjcmlwdA==")); //"我喜欢 javascript"
FormData:

我们只需要使用new FormData()创建对象,然后append键值对,后用ajax向后台发生即可。

这里是往FormData对象添加blob字段。

注:使用Ajax将这个FormData对象提交到服务器上时,所发送的HTTP请求头中代表那个Blob对象所包含文件的文件名称的"Content-Disposition"请求头的值会是一个空字符串,这会引发某些服务器程序上的错误.从Gecko 7.0开始,这种情况下发送的文件名称改为"blob"这个字符串.

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
 <title>Document</title>
 <script src="http://apps.bdimg.com/libs/zepto/1.1.4/zepto.min.js"></script> <!--引用baidu-->
</head>
<style>
.uploadPic{
 width: 92%;
 position: relative;
 margin: 0 auto;
 height: 2.8rem;
 line-height: 2.8rem;
 font-size: 1.3rem;
 border-radius: 4px;
 color: #fff;
 text-align: center;
 background-color: #72bcc5;
}
.uploadPic>input{
 position: absolute;
 display: block;
 width: 100%;
 height: 100%;
 right: 0;
 top: 0;
 opacity: 0;
}
.uploadPic>img{
 border:none;
}
</style>
<body>
 <p id="uploadPic" class="uploadPic">
 <span>拍摄</span>
 <input type="file" > <!--这里可以添加multiple="true"属性,用来添加多张图片,然后对this.file[]数组操作-->
 <p style="line-height: 1rem;margin: 0.5rem 0;"><progress id="progress" value="0" max="100" style="width: 100%;"></progress></p> 
 <img src="" width="100%" style="height: 21rem;">
 </p>
</body>
<script>
 function upload(file, callBack) {
 var loading=0;
 var total=file.size;
 if(window.FileReader){
 $("#progress")[0].value=0;
 var fileReader = new FileReader();
 fileReader.onload = function() {
 console.log(fileReader.readyState); //读取完成
 compressPic(this.result,callBack)
 };
 fileReader.onerror = function() {
 console.log(fileReader.error);
 };
 fileReader.onprogress = function (e){
 console.log(fileReader.readyState); //读取中
 loading += e.loaded;
 $("#progress")[0].value=(loading / total) * 100; 
 }
 console.log(fileReader.readyState); //未读取
 fileReader.readAsDataURL(file)
 }else{
 alert("您的浏览器不支持FileReader");
 }
 }
 function baseConvertToBlob(picData, type, size) {
 type = type || "";
 size = size || 512;
 var decodeFileData = atob(picData); //此处用atob解码,转码函数btoa。在使用方法时注意操作中文时,需对中文decodeURIComponent转换
 var dataArray = [];
 var len = decodeFileData.length;
 for (var i = 0; i < len; i += size) {
 var pieceData = decodeFileData.slice(i, i + size); //这里做了一个512的分组
 var arr = new Array(pieceData.length);
 for (var j = 0; j < pieceData.length; j++) {
 arr[j] = pieceData.charCodeAt(j)
 }
 var u8a = new Uint8Array(arr);
 dataArray.push(u8a)
 }
 return new Blob(dataArray, {type: type})
 }
 function compressPic(picData,callBack) {
 var img=new Image();
 img.onload = function(){
 var width = img.width;
 var height = img.height;
 var standard=800; //以800为基准压缩
 if (width > standard || height > standard) {
 var rate = Math.max(width / standard, height / standard);
 width /= rate;
 height /= rate
 }
 var canvas = document.createElement("canvas");
 canvas.width = width;
 canvas.height = height;
 var context = canvas.getContext("2d");
 context.fillRect(0, 0, canvas.width, canvas.height);
 context.drawImage(img, 0, 0, width, height);
 var data = canvas.toDataURL("image/jpeg", 1);
 //var blobData=baseConvertToBlob(data.replace(/^.*?,/, ""), "image/jpeg") //-----需要去掉符号,不然使用atob方法报错
 //doAjax(new FormData().append('image',data)); //后续可以这样做,转换成Blob字段,组装FormData,发送至后台
 console.log("the after canvas compress size : " + data.length);
 callBack(data)
 };
 img.src=picData;
 console.log("the before canvas conpress size : "+picData.length);
 }
 $("#uploadPic input").change(function() {
 var file=this.files[0];
 upload(file, function(picData){
 $("#uploadPic img")[0].src = picData; //预览
 }
 );
 });
</script>
</html>

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

JS中特性与UA检测

Ajax的工作原理核心以及对象

下载本文
显示全文
专题