javascript和HTML5上传图片之前实现预览效果
一:FileList对象与file对象
FileList对象表示用户选择的文件列表,在HTML4中,file控件内只允许放置一个文件,但是到了HTML5中,通过添加multiple属性,file控件内允许一次放置多个文件,控件内的每一个用户选择的文件都是一个file对象,而FileList对象是file对象的列表;
比如如下代码:
选择文件<input type="file" id="file" multiple size="80"/>
<input type="button" onclick="ShowFileName();" value="文件上传"/>
我们可以按住ctrl键选择多个文件;
JS代码如下:
function ShowFileName() {
var files = document.getElementById("file").files;
for(var i = 0; i < files.length; i+=1) {
var file = files[i];
console.log(file);
console.log(file.name);
}
}
我们先打印下file对象有哪些属性,在safari截图如下:
如上图可以看到有文件名(name)属性,文件大小(size)属性,最后修改时间,还有type属性等;
二:Blob对象
在HTML5中,新增一个Blob对象,代表原始二进制数据,我们上面提到的file对象也继承了这个Blob对象;
Blob对象有2个属性,size属性表示一个Blob对象的字节长度,type属性表示Blob的MIME类型,如果是未知类型,则返回一个空字符串。
如下代码:
选择文件<input type="file" id="file" multiple size="80" accept="image/*"/>
<input type="button" onclick="ShowFileType();" value="显示文件信息"/>
文件字节长度:<span id="size"></span><br/>
文件类型:<span id="type"></span>
JS代码如下:
function ShowFileType() {
var file = document.getElementById("file").files[0];
var size = document.getElementById("size");
var type = document.getElementById("type");
// 显示文件字节长度
size.innerHTML = file.size;
// 显示文件类型
type.innerHTML = file.type;
console.log(file);
}
我们打印出file,如下图所示:
三:FileReader对象
FileReader对象有5种方法,其中四种用于读取文件,另一种用来读取过程中断,需要注意的是:无论读取成功与失败,方法并不会返回读取结果,而是将结果保存在result属性中。此对象也是异步的。
FileReader对象的方法如下:
readAsBinaryString(file): 这个方法将blob对象或文件中的数据读取为二进制字符串,通常我们将它传送到服务器端,服务器端可以通过这段字符串存储文件。
readAsText(file,encoding): 以纯文本形式读取文件,将读取到的文本保存在result属性中,第二个参数用于指定编码类型,可选的。
readAsDataURL(file): 读取文件并将文件以数据URL的形式保存在result属性中。
readAsArrayBuffer(file): 读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中。
FileReader对象的事件如下:
onabort: 数据读取中断时触发
onerror: 数据读取出错时触发
onloadstart: 数据读取开始时触发
onprogress: 数据读取中
onload: 数据读取成功完成时触发
onloadend: 数据读取完成时触发,无论成功或失败。
我们可以先看看demo,如何使用FileReader对象中前面三个方法;注意:fileReader对象读取的数据都保存在result中,如下代码:
<p>
<label>请选择一个文件:</label>
<input type="file" id="file" />
<input type="button" value="读取图像" onclick = "readAsDataURL()"/>
<input type="button" value="读取二进制数据" onclick = "readAsBinaryString()"/>
<input type="button" value="读取文本文件" onclick = "readAsText()"/>
</p>
<div id="result"></div>
JS代码如下:
<script>
var result = document.getElementById("result");
if(typeof FileReader == 'undefined') {
result.innerHTML = "抱歉,你的浏览器不支持FileReader";
}
// 将文件以Data URL形式进行读入页面
function readAsDataURL(){
// 检查是否为图像类型
var simpleFile = document.getElementById("file").files[0];
if(!/image\/\w+/.test(simpleFile.type)) {
alert("请确保文件类型为图像类型");
return false;
}
var reader = new FileReader();
// 将文件以Data URL形式进行读入页面
reader.readAsDataURL(simpleFile);
reader.onload = function(e){
console.log(this.result);
result.innerHTML = '<img src="'+this.result+'" alt=""/>';
}
}
// 将文件以二进制形式读入页面
function readAsBinaryString(){
// 检查是否为图像类型
var simpleFile = document.getElementById("file").files[0];
if(!/image\/\w+/.test(simpleFile.type)) {
alert("请确保文件类型为图像类型");
return false;
}
var reader = new FileReader();
// 将文件以二进制形式进行读入页面
reader.readAsBinaryString(simpleFile);
reader.onload = function(e){
// 在页面上显示二进制数据
result.innerHTML = this.result;
}
}
// 将文件以文本形式读入页面中
function readAsText(){
var simpleFile = document.getElementById("file").files[0];
var reader = new FileReader();
// 将文件以文本形式读入页面中
reader.readAsText(simpleFile);
reader.onload = function(e){
result.innerHTML = this.result;
}
}
</script>
如上代码,如果需要演示的话,可以复制代码到文本编辑器去,预览下即可,这里就不截图了;但是如上代码,在safari浏览器就不支持了~ 截图如下:
四:btoa方法与atob方法
在HTML5中,btoa方法与atob方法来支持base64编码,b可以被理解为一串二进制数据,a可以被理解为一个ASCLL码字符串,btoa的使用方法如下:
var result = window.btoa(data);
该方法用于将一串字符串进行base64编码处理,该方法使用一个参数,参数值由一串二进制数据组成的Unicode字符串,该方法返回编码后的base64格式的字符串。
atob方法使用如下所示:
var result = window.atob(data);
该方法用于将一串经过base64编码后的base64格式的字符串进行解码处理,该方法使用一个参数,参数值为一串经过base64编码后的字符串,方法返回经过解码后的一串由二进制数据组成的Unicode字符串;
浏览器支持:firefox,chrome,opera10.5+及IE10+
什么时候使用btoa方法呢?
当服务器端数据库中直接保存了是图片的二进制数据及图片文件的格式时,当我们需要根据此二进制数据来渲染图片的时候非常有用;如下代码:
<p>
<label>请选择一个文件:</label>
<input type="file" id="file"/>
<input type="button" value="读取图像" onclick = "readPicture()" id="btnReadPicture"/>
</p>
<div id="result"></div>
JS代码如下:
if(typeof FileReader == 'undefined') {
result.innerHTML = "抱歉,你的浏览器不支持FileReader";
}
function readPicture(){
// 检查是否为图像类型
var simpleFile = document.getElementById("file").files[0];
if(!/image\/\w+/.test(simpleFile.type)) {
alert("请确保文件类型为图像类型");
return false;
}
var reader = new FileReader();
// 将文件以二进制文件读入页面中
reader.readAsBinaryString(simpleFile);
reader.onload = function(f){
var result = document.getElementById("result");
var src = "data:" + simpleFile.type + ";base64," + window.btoa(this.result);
result.innerHTML = '<img src ="'+src+'"/>';
}
}
当我们选择一张图像的时候,点击读取图像按钮即可生成一张图片,虽然此方法我们还可以使用我们上面介绍的readAsDataURL的方法也可以直接读取图像,但是当服务器中直接是保存的是二进制文件的话,我们可以直接使用btoa此方法生成图片即可;
下面我们可以看看atob的demo如下:
我们可以使用canvas来绘制一张图片后,点击上传图片按钮后,首先通过canvas元素的toDataURL()方法获取该图片的url地址,最后获取该URL地址中的base64格式的字符串,最后使用atob方法将其解码为一串二进制数据,并将该二进制数据提交到服务器端;如下代码:
<input type="button" value="上传图片" onclick="imgSave()"/><br/>
<canvas id="canvas" width="400" height="300"></canvas>
JS代码如下:
<script>
var canvas;
function draw(id) {
canvas = document.getElementById(id);
var context = canvas.getContext('2d');
context.fillStyle = 'rgb(0,0,255)';
context.fillRect(0,0,canvas.width,canvas.height);
context.fillStyle = 'rgb(255,255,0)';
context.fillRect(10,20,50,50);
}
draw('canvas');
function imgSave(){
var data = canvas.toDataURL("image/png");
data = data.replace("data:image/png;base64,","");
var xhr = new XMLHttpRequest();
xhr.open("POST","uploadImg.php");
xhr.send(window.atob(data));
}
</script>
uploadImg.php自己写;
下面我们来做一个本地图片上传前预览效果,但是safari不支持,所以在做移动端的同学可能不好了,特别是在IOS6下就不支持哦,应该还有其他办法可以解决的,我们可以看看百度的插件,网址如下:
http://fex.baidu.com/webuploader/demo.html
之前我是做了一个上传本地图片之前预览效果,如下链接:
http://www.cnblogs.com/tugenhua0707/p/3568134.html
今天为了学习FileReader,我们可以再来学习下;之前的本地上传图片预览的话,不支持IE10+, 且把页面放在服务器端在IE下会有bug,如下所示:
如上所示,在IE下 这个方法 document.selection.createRange() 不支持,因此为了修复这个bug和在IE10+以上的话,今天又特意研究了下, 在file控件下获取焦点情况下 document.selection.createRange() 将会拒绝访问,所以我们要失去下焦点。我们可以再加一句代码就可以支持了 file.blur();
IE10+的bug的话,我们可以使用html5的上面介绍的文件API来解决,先判断是不是IE,如果是的话,且小于10的话,使用滤镜的方法解决图片上传的问题,如果是其他浏览器的话,就使用html5的文件上传方法;但是safari没有处理好,原因是safari不支持html5的fileReader的API,所以如果在移动端开发的图片,如果需要兼容IOS6和6+的话,请注意一下,并不支持~ 当然如果大家有更好的方案来支持IOS6的话,请留言,可以一起总结,一起学习~
五:上传图片之前预览效果demo(Safari不兼容)
1. 在标准浏览器下(IE10+)使用HTML5中文件API即可解决上传图片前预览效果;在这里有2中方案可以解决,第一种是使用文件API,如下代码:
function html5Reader(file) {
var file = file.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e){
var pic = document.getElementById("img");
pic.src=this.result;
}
}
2. 第二种方案是使用 URL.createObjectURL(fileObj) 这个方法和canvas技术, 我们先来看看 支持这个 URL.createObjectURL(fileObj) 的浏览器有哪些,我们可以点击下面的连接查看:
http://caniuse.com/#search=createObjectURL/
实现代码如下:
function html5Reader(file) {
var fileObj = file.files[0],
img = document.getElementById("img");
// URL.createObjectURL safari不支持
img.src = URL.createObjectURL(fileObj);
img.onload =function() {
var data = getBase64Image(img);
console.log(data); // 打印出base64编码
}
}
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height; var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();
var dataURL = canvas.toDataURL("image/"+ext);
return dataURL;
}
HTML代码如下:
<input type="file" id="logo" name="logo" accept="image/*">
<img src= '' id="img"/>
<div id="btn" style="margin-top:50px;font-size:40px;">btn</div>
<canvas id="myCanvas"></canvas>
所有的JS代码如下:
<script>
var EventUtil = {
addHandler: function(element,type,handler) {
if(element.addEventListener) {
element.addEventListener(type,handler,false);
}else if(element.attachEvent) {
element.attachEvent("on"+type,handler);
}else {
element["on" +type] = handler;
}
}
};
var btn = document.getElementById("btn");
var pic = document.getElementById("img");
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height; var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();
var dataURL = canvas.toDataURL("image/"+ext);
return dataURL;
}
var ua = navigator.userAgent.toLowerCase();
EventUtil.addHandler(btn,'click',function(){
var file = document.getElementById("logo"); var ext=file.value.substring(file.value.lastIndexOf(".")+1).toLowerCase(); // gif在IE浏览器暂时无法显示
if(ext!='png'&&ext!='jpg'&&ext!='jpeg'){
alert("图片的格式必须为png或者jpg或者jpeg格式!");
return;
}
if(/msie ([^;]+)/.test(ua)) {
var lowIE10 = RegExp["$1"]*1;
if(lowIE10 == 6){
// IE6浏览器设置img的src为本地路径可以直接显示图片
file.select();
// 在file控件下获取焦点情况下 document.selection.createRange() 将会拒绝访问,所以我们要失去下焦点。
file.blur(); var reallocalpath = document.selection.createRange().text;
pic.src = reallocalpath;
}else if(lowIE10 > 6 && lowIE10 < 10){
// IE7~9 IE10+按照html5的标准去处理
file.select();
// 在file控件下获取焦点情况下 document.selection.createRange() 将会拒绝访问,所以我们要失去下焦点。
file.blur(); var reallocalpath = document.selection.createRange().text;
// 非IE6版本的IE由于安全问题直接设置img的src无法显示本地图片,但是可以通过滤镜来实现
pic.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src=\"" + reallocalpath + "\")";
// 设置img的src为base64编码的透明图片 取消显示浏览器默认图片
pic.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
}else if(lowIE10 >= 10) {
html5Reader(file);
}
}else {
html5Reader(file);
}
}); function html5Reader(file) {
var fileObj = file.files[0],
img = document.getElementById("img");
// URL.createObjectURL safari不支持
img.src = URL.createObjectURL(fileObj);
img.onload =function() {
var data = getBase64Image(img);
console.log(data); // 打印出base64编码
}
/*
var file = file.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e){
var pic = document.getElementById("img");
pic.src=this.result;
}*/
}
</script>
javascript和HTML5上传图片之前实现预览效果的更多相关文章
- 基于jquery实现的上传图片及图片预览效果代码
<!DOCTYPE html> <html> <head> <title>HTML5上传图片预览</title> <meta http ...
- HTML5 CSS3 经典案例:无插件拖拽上传图片 (支持预览与批量) (二)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/31513065 上一篇已经实现了这个项目的整体的HTML和CSS: HTML5 C ...
- html5 图片转base64预览显示
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...
- HTML5图片拖拽预览原理及实现
一.前言 这两天恰好有一位同事问我怎样做一个图片预览功能.作为现代人的我们首先想到的当然是HTML5啦,其实HTML5做图片预览已经是一个老生常谈的问题了.我在这里就简单说说其中相关的一些东西,当然会 ...
- HTML5 图片上传预览
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8& ...
- js兼容火狐显示上传图片预览效果
js兼容火狐显示上传图片预览效果[谷歌也适用] <!doctype html> <html> <head> <meta content="text/ ...
- JavaScript实现图片裁剪预览效果~(第一个小玩具)
感觉开始学习的前一个月真的太不珍惜慕课网的资源了 上面蛮多小玩意真的蛮适合我这样刚入门JavaScript的同学加深使用理解 大概收藏了百来门或大或小的课程 有一个感觉就是学这个真的比光是看书看概 ...
- 用html5文件api实现移动端图片上传&预览效果
想要用h5在移动端实现图片上传&预览效果,首先要了解html5的文件api相关知识(所有api只列举本功能所需): 1.Blob对象 Blob表示原始二进制数据,Html5的file对象就继 ...
- jquery实现上传图片及图片大小验证、图片预览效果代码
jquery实现上传图片及图片大小验证.图片预览效果代码 jquery实现上传图片及图片大小验证.图片预览效果代码 上传图片验证 */ function submit_upload_picture() ...
随机推荐
- MVC5 + EF6 + Bootstrap3 (12) 新建数据
Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-create.html 系列教程:MVC5 + EF6 + ...
- 随便谈谈用canvas来实现文字图片粒子化
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 看了岑安大大的教程http://www.cnblogs.com/hongru/archive/2012/03/28/2420415.htm ...
- Git.Framework 框架随手记--ORM新增操作
本篇主要记录具体如何新增数据,废话不多说,开始进入正文. 一. 生成工程结构 上一篇已经说到了如何生成工程结构,这里在累述一次. 1. 新建项目总体结构 使用VS新建项目结构,分层结构可以随意.我们使 ...
- EntityFramework_MVC4中EF5 新手入门教程之二 ---2.执行基本的 CRUD 功能
在前面的教程中,您创建 MVC 应用程序中,存储和显示数据使用实体框架和 SQL 服务器 LocalDB.在本教程中,您会审查和自定义的 CRUD (创建. 读取. 更新. 删除) MVC 脚手架会自 ...
- solr导入mysql数据库
感谢ITeye的博主viskyzz分享的经验,笔者基本参考ta的方法.然而,解决中间出现的问题时也融入了自己的经验. 查看ta的原文请戳: http://tbwuming.iteye.com/blog ...
- asp.net 学习
1.维护数据库的完整性.一致性.你喜欢用触发器还是自写业务逻辑?为什么? 答:尽可能用约束(包括CHECK.主键.唯一键.外键.非空字段)实现,这种方式的效率最好:其次用触发器,这种方式可以保证无论何 ...
- Eclipse-插件的安装之link文件方法
1. 我的eclipse路径为eclipse_Home,在eclipse文件夹下建文件夹MyPlugins. 2. 下载插件并解压得到包含features和plugins的文件夹theXXX. 3. ...
- 前端筑基篇(一)->ajax跨域原理以及解决方案
说明 跨域主要是由于浏览器的“同源策略”引起,分为多种类型,本文主要探讨Ajax请求跨域问题 前言 参考来源 什么是跨域 ajax跨域的表现 跨域的原理 如何解决跨域问题 JSONP方式解决跨域问题 ...
- 【前端】less学习
Less 是什么? Less is more,than CSS. Less就是搞笑高效编写和维护CSS的一种语法. 1.下载Koala考拉,一款国人编写的less开发器. 2.可以用Sublime T ...
- Yii2修改默认布局
public $layout = 'layout';//在类中定义一个变量,名为$layout的php文件 <?php echo $content; ?>