点评:创建一个只管的用户界面,并允许你控制图片的大小。上传到服务器端的数据,并不需要处理enctype为 multi-part/form-data 的情况,仅仅一个简单的POST表单处理程序就可以了. 好了,下面附上完整的代码示例
示例地址:
Canvas Resize Demo yF4HTML5中文学习网 - HTML5先行者学习网
原文作者:Dr. Tom Trenka
yF4HTML5中文学习网 - HTML5先行者学习网原文日期: 2013年8月6日
yF4HTML5中文学习网 - HTML5先行者学习网翻译日期: 2013年8月8日
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网Tom Trenka 能为"我"的博客写一篇文章,对我来说是一个巨大的荣誉。Tom是Dojo框架的最初贡献者之一,也是我在SitePen公司的良师益友.我见证了他最顶级的天才能力,并且他总是第一个以前瞻性的解决方案预见了很多棘手的问题。他总是站在局外思考,打破常规但却又坚实可靠地解决边缘问题。本文就是一个完美的例证。
yF4HTML5中文学习网 - HTML5先行者学习网最近我总是被问道要创造一个用户接口API,允许用户上传图片到服务器上(伴随其他的事情),并能在我们公司提供支持的大量网站的客户端上使用。通常来说这都是很容易的事情——创建一个form表单,添加一个file类型的input输入框,让用户从电脑里选择图片,并在form标签上设置enctype="multipart/form-data"表单属性,然后上传即可。非常简单,不是吗?事实上,这里有一个足够简单的例子;
点击进入 yF4HTML5中文学习网 - HTML5先行者学习网但是如果你想要通过某些方式预先处理一下图片再上传,那该怎么办?比如说,你必须先压缩图片尺寸,或者需要图片只能是某些种类的格式,如 png 或者jpg,你怎么办?
yF4HTML5中文学习网 - HTML5先行者学习网用canvas来解决!
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网Canvas简介 yF4HTML5中文学习网 - HTML5先行者学习网canvas 是一个HTML5新增的DOM元素,允许用户在页面上直接地绘制图形,通常是使用JavaScript.而不同的格式标准也是不同的,比如SVG是光栅API(raster API) 而VML却是向量API(vector API).可以考虑使用Adobe Illustrator(矢量图)作图与使用 Adobe Photoshop (光栅图)作图的区别。
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网在canvas(画布)上能做的事情就是读取和渲染图像,并且允许你通过JavaScript操纵图像数据。已经有很多现存的文章来为你演示基本的图像处理——主要关注与各种不同的图像过滤技术( image filtering techniques)——但我们需要的仅仅是缩放图片并转换到特定的文件格式,而canvas完全可以做到这些事情。
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网我们假定的需求,比如图像高度不超过100像素,不管原始图像有多高。基本的代码如下所示:
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
// 参数,最大高度 yF4HTML5中文学习网 - HTML5先行者学习网
var MAX_HEIGHT = 100; yF4HTML5中文学习网 - HTML5先行者学习网
// 渲染 yF4HTML5中文学习网 - HTML5先行者学习网
function render(src){ yF4HTML5中文学习网 - HTML5先行者学习网
// 创建一个 Image 对象 yF4HTML5中文学习网 - HTML5先行者学习网
var image = new Image(); yF4HTML5中文学习网 - HTML5先行者学习网
// 绑定 load 事件处理器,加载完成后执行 yF4HTML5中文学习网 - HTML5先行者学习网
image.onload = function(){ yF4HTML5中文学习网 - HTML5先行者学习网
// 获取 canvas DOM 对象 yF4HTML5中文学习网 - HTML5先行者学习网
var canvas = document.getElementById("myCanvas"); yF4HTML5中文学习网 - HTML5先行者学习网
// 如果高度超标 yF4HTML5中文学习网 - HTML5先行者学习网
if(image.height > MAX_HEIGHT) { yF4HTML5中文学习网 - HTML5先行者学习网
// 宽度等比例缩放 *= yF4HTML5中文学习网 - HTML5先行者学习网
image.width *= MAX_HEIGHT / image.height; yF4HTML5中文学习网 - HTML5先行者学习网
image.height = MAX_HEIGHT; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
// 获取 canvas的 2d 环境对象, yF4HTML5中文学习网 - HTML5先行者学习网
// 可以理解Context是管理员,canvas是房子 yF4HTML5中文学习网 - HTML5先行者学习网
var ctx = canvas.getContext("2d"); yF4HTML5中文学习网 - HTML5先行者学习网
// canvas清屏 yF4HTML5中文学习网 - HTML5先行者学习网
ctx.clearRect(0, 0, canvas.width, canvas.height); yF4HTML5中文学习网 - HTML5先行者学习网
// 重置canvas宽高 yF4HTML5中文学习网 - HTML5先行者学习网
canvas.width = image.width; yF4HTML5中文学习网 - HTML5先行者学习网
canvas.height = image.height; yF4HTML5中文学习网 - HTML5先行者学习网
// 将图像绘制到canvas上 yF4HTML5中文学习网 - HTML5先行者学习网
ctx.drawImage(image, 0, 0, image.width, image.height); yF4HTML5中文学习网 - HTML5先行者学习网
// !!! 注意,image 没有加入到 dom之中 yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
// 设置src属性,浏览器会自动加载。 yF4HTML5中文学习网 - HTML5先行者学习网
// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。 yF4HTML5中文学习网 - HTML5先行者学习网
image.src = src; yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网在上面的例子中,你可以使用canvas 的 toDataURL() 方法获取图像的 Base64编码的值(可以类似理解为16进制字符串,或者二进制数据流).
yF4HTML5中文学习网 - HTML5先行者学习网注意: canvas 的 toDataURL() 获取的URL以字符串开头,有22个无用的数据 "data:image/png;base64,",需要在客户端或者服务端进行过滤.
yF4HTML5中文学习网 - HTML5先行者学习网原则上只要浏览器支持,URL地址的长度是没有限制的,而1024的长度限制,是老一代IE所独有的。
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网请问,如何获取我们需要的图像呢?
yF4HTML5中文学习网 - HTML5先行者学习网好孩子,很高兴你能这么问。你并不能通过File 输入框来直接处理,你从这个文件输入框元素所能获取的仅仅是用户所选择文件的path路径。按照常规想象,你可以通过这个path路径信息来加载图像,但是,在浏览器里面这是不现实的。(译者注:浏览器厂商必须保证自己的浏览器绝对安全,才能获得市场,至少避免媒体的攻击,如果允许这样做,那恶意网址可以通过拼凑文件路径来尝试获取某些敏感信息).
yF4HTML5中文学习网 - HTML5先行者学习网为了实现这个需求,我们可以使用HTML5的File API 来读取用户磁盘上的文件,并用这个file来作为图像的源(src,source).
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网File API简介 yF4HTML5中文学习网 - HTML5先行者学习网新的File API接口是在不违背任何安全沙盒规则下,读取和列出用户文件目录的一个途径—— 通过沙盒(sandbox)限制,恶意网站并不能将病毒写入用户磁盘,当然更不能执行。
yF4HTML5中文学习网 - HTML5先行者学习网我们要使用的文件读取对象叫做 FileReader,FileReader允许开发者读取文件的内容(具体浏览器的实现方式可能大不相同)。
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网假设我们已经获取了图像文件的path路径,那么依赖前面的代码,使用FileReader来加载和渲染图像就变得很容易了:
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
// 加载 图像文件(url路径) yF4HTML5中文学习网 - HTML5先行者学习网
function loadImage(src){ yF4HTML5中文学习网 - HTML5先行者学习网
// 过滤掉 非 image 类型的文件 yF4HTML5中文学习网 - HTML5先行者学习网
if(!src.type.match(/image.*/)){ yF4HTML5中文学习网 - HTML5先行者学习网
if(window.console){ yF4HTML5中文学习网 - HTML5先行者学习网
console.log("选择的文件类型不是图片: ", src.type); yF4HTML5中文学习网 - HTML5先行者学习网
} else { yF4HTML5中文学习网 - HTML5先行者学习网
window.confirm("只能选择图片文件"); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
return; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
// 创建 FileReader 对象 并调用 render 函数来完成渲染. yF4HTML5中文学习网 - HTML5先行者学习网
var reader = new FileReader(); yF4HTML5中文学习网 - HTML5先行者学习网
// 绑定load事件自动回调函数 yF4HTML5中文学习网 - HTML5先行者学习网
reader.onload = function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// 调用前面的 render 函数 yF4HTML5中文学习网 - HTML5先行者学习网
render(e.target.result); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
// 读取文件内容 yF4HTML5中文学习网 - HTML5先行者学习网
reader.readAsDataURL(src); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网请问,如何获取文件呢?
yF4HTML5中文学习网 - HTML5先行者学习网小白兔,要有耐心!我们的下一步就是获取文件,当然有好多方法可以实现啦。例如:你可以用文本框让用户输入文件路径,但很显然大多数用户都不是开发者,对输入什么值根本就不了解.
yF4HTML5中文学习网 - HTML5先行者学习网为了用户使用方便,我们采用 Drag and Drop API接口。
yF4HTML5中文学习网 - HTML5先行者学习网yF4HTML5中文学习网 - HTML5先行者学习网使用 Drag and Drop API yF4HTML5中文学习网 - HTML5先行者学习网拖拽接口(Drag and Drop)非常简单——在大多数的DOM元素上,你都可以通过绑定事件处理器来实现. 只要用户从磁盘上拖动一个文件到dom对象上并放开鼠标,那我们就可以读取这个文件。代码如下:
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
function init(){ yF4HTML5中文学习网 - HTML5先行者学习网
// 获取DOM元素对象 yF4HTML5中文学习网 - HTML5先行者学习网
var target = document.getElementById("drop-target"); yF4HTML5中文学习网 - HTML5先行者学习网
// 阻止 dragover(拖到DOM元素上方) 事件传递 yF4HTML5中文学习网 - HTML5先行者学习网
target.addEventListener("dragover", function(e){e.preventDefault();}, true); yF4HTML5中文学习网 - HTML5先行者学习网
// 拖动并放开鼠标的事件 yF4HTML5中文学习网 - HTML5先行者学习网
target.addEventListener("drop", function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// 阻止默认事件,以及事件传播 yF4HTML5中文学习网 - HTML5先行者学习网
e.preventDefault(); yF4HTML5中文学习网 - HTML5先行者学习网
// 调用前面的加载图像 函数,参数为dataTransfer对象的第一个文件 yF4HTML5中文学习网 - HTML5先行者学习网
loadImage(e.dataTransfer.files[0]); yF4HTML5中文学习网 - HTML5先行者学习网
}, true); yF4HTML5中文学习网 - HTML5先行者学习网
var setheight = document.getElementById("setheight"); yF4HTML5中文学习网 - HTML5先行者学习网
var maxheight = document.getElementById("maxheight"); yF4HTML5中文学习网 - HTML5先行者学习网
setheight.addEventListener("click", function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
var value = maxheight.value; yF4HTML5中文学习网 - HTML5先行者学习网
if(/^/d+$/.test(value)){ yF4HTML5中文学习网 - HTML5先行者学习网
MAX_HEIGHT = parseInt(value); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
e.preventDefault(); yF4HTML5中文学习网 - HTML5先行者学习网
},true); yF4HTML5中文学习网 - HTML5先行者学习网
var btnsend = document.getElementById("btnsend"); yF4HTML5中文学习网 - HTML5先行者学习网
btnsend.addEventListener("click", function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
sendImage(); yF4HTML5中文学习网 - HTML5先行者学习网
},true); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网我们还可以做一些其他的处理,比如显示预览图。但如果不想压缩图片的话,那很可能没什么用。我们将采用Ajax通过HTTP 的post方式上传图片数据。下面的例子是使用Dojo框架来完成请求的,当然你也可以采用其他的Ajax技术来实现.
yF4HTML5中文学习网 - HTML5先行者学习网Dojo 代码如下:
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
// 译者并不懂Dojo,所以将在后面附上jQuery的实现 yF4HTML5中文学习网 - HTML5先行者学习网
// Remember that DTK 1.7+ is AMD! yF4HTML5中文学习网 - HTML5先行者学习网
require(["dojo/request"], function(request){ yF4HTML5中文学习网 - HTML5先行者学习网
// 设置请求URL,参数,以及回调。 yF4HTML5中文学习网 - HTML5先行者学习网
request.post("image-handler.php", { yF4HTML5中文学习网 - HTML5先行者学习网
data: { yF4HTML5中文学习网 - HTML5先行者学习网
imageName: "myImage.png", yF4HTML5中文学习网 - HTML5先行者学习网
imageData: encodeURIComponent(document.getElementById("canvas").toDataURL("image/png")) yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
}).then(function(text){ yF4HTML5中文学习网 - HTML5先行者学习网
console.log("The server returned: ", text); yF4HTML5中文学习网 - HTML5先行者学习网
}); yF4HTML5中文学习网 - HTML5先行者学习网
}); yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网jQuery 实现如下:
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
// 上传图片,jQuery版 yF4HTML5中文学习网 - HTML5先行者学习网
function sendImage(){ yF4HTML5中文学习网 - HTML5先行者学习网
// 获取 canvas DOM 对象 yF4HTML5中文学习网 - HTML5先行者学习网
var canvas = document.getElementById("myCanvas"); yF4HTML5中文学习网 - HTML5先行者学习网
// 获取Base64编码后的图像数据,格式是字符串 yF4HTML5中文学习网 - HTML5先行者学习网
// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。 yF4HTML5中文学习网 - HTML5先行者学习网
var dataurl = canvas.toDataURL("image/png"); yF4HTML5中文学习网 - HTML5先行者学习网
// 为安全 对URI进行编码 yF4HTML5中文学习网 - HTML5先行者学习网
// data%3Aimage%2Fpng%3Bbase64%2C 开头 yF4HTML5中文学习网 - HTML5先行者学习网
var imagedata = encodeURIComponent(dataurl); yF4HTML5中文学习网 - HTML5先行者学习网
//var url = $("#form").attr("action"); yF4HTML5中文学习网 - HTML5先行者学习网
// 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址 yF4HTML5中文学习网 - HTML5先行者学习网
// <input type="hidden" name="action" value="receive.jsp" /> yF4HTML5中文学习网 - HTML5先行者学习网
var url = $("input[name='action']").val(); yF4HTML5中文学习网 - HTML5先行者学习网
// 2. 也可以直接用某个dom对象的属性来获取 yF4HTML5中文学习网 - HTML5先行者学习网
// <input id="imageaction" type="hidden" action="receive.jsp"> yF4HTML5中文学习网 - HTML5先行者学习网
// var url = $("#imageaction").attr("action"); yF4HTML5中文学习网 - HTML5先行者学习网
// 因为是string,所以服务器需要对数据进行转码,写文件操作等。 yF4HTML5中文学习网 - HTML5先行者学习网
// 个人约定,所有http参数名字全部小写 yF4HTML5中文学习网 - HTML5先行者学习网
console.log(dataurl); yF4HTML5中文学习网 - HTML5先行者学习网
//console.log(imagedata); yF4HTML5中文学习网 - HTML5先行者学习网
var data = { yF4HTML5中文学习网 - HTML5先行者学习网
imagename: "myImage.png", yF4HTML5中文学习网 - HTML5先行者学习网
imagedata: imagedata yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
jQuery.ajax( { yF4HTML5中文学习网 - HTML5先行者学习网
url : url, yF4HTML5中文学习网 - HTML5先行者学习网
data : data, yF4HTML5中文学习网 - HTML5先行者学习网
type : "POST", yF4HTML5中文学习网 - HTML5先行者学习网
// 期待的返回值类型 yF4HTML5中文学习网 - HTML5先行者学习网
dataType: "json", yF4HTML5中文学习网 - HTML5先行者学习网
complete : function(xhr,result) { yF4HTML5中文学习网 - HTML5先行者学习网
//console.log(xhr.responseText); yF4HTML5中文学习网 - HTML5先行者学习网
var $tip2 = $("#tip2"); yF4HTML5中文学习网 - HTML5先行者学习网
if(!xhr){ yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text('网络连接失败!'); yF4HTML5中文学习网 - HTML5先行者学习网
return false; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
var text = xhr.responseText; yF4HTML5中文学习网 - HTML5先行者学习网
if(!text){ yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text('网络错误!'); yF4HTML5中文学习网 - HTML5先行者学习网
return false; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
var json = eval("("+text+")"); yF4HTML5中文学习网 - HTML5先行者学习网
if(!json){ yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text('解析错误!'); yF4HTML5中文学习网 - HTML5先行者学习网
return false; yF4HTML5中文学习网 - HTML5先行者学习网
} else { yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text(json.message); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
//console.dir(json); yF4HTML5中文学习网 - HTML5先行者学习网
//console.log(xhr.responseText); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
}); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网OK,搞定!你还需要做的,就是创建一个只管的用户界面,并允许你控制图片的大小。上传到服务器端的数据,并不需要处理enctype为 multi-part/form-data 的情况,仅仅一个简单的POST表单处理程序就可以了.
yF4HTML5中文学习网 - HTML5先行者学习网好了,下面附上完整的代码示例:
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> yF4HTML5中文学习网 - HTML5先行者学习网
<% yF4HTML5中文学习网 - HTML5先行者学习网
String path = request.getContextPath(); yF4HTML5中文学习网 - HTML5先行者学习网
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; yF4HTML5中文学习网 - HTML5先行者学习网
%> yF4HTML5中文学习网 - HTML5先行者学习网
<!DOCTYPE html> yF4HTML5中文学习网 - HTML5先行者学习网
<html> yF4HTML5中文学习网 - HTML5先行者学习网
<head> yF4HTML5中文学习网 - HTML5先行者学习网
<title>通过Canvas及File API缩放并上传图片</title> yF4HTML5中文学习网 - HTML5先行者学习网
<meta http-equiv="pragma" content="no-cache"> yF4HTML5中文学习网 - HTML5先行者学习网
<meta http-equiv="cache-control" content="no-cache"> yF4HTML5中文学习网 - HTML5先行者学习网
<meta http-equiv="expires" content="0"> yF4HTML5中文学习网 - HTML5先行者学习网
<meta http-equiv="keywords" content="Canvas,File,Image"> yF4HTML5中文学习网 - HTML5先行者学习网
<meta http-equiv="description" content="2013年8月8日,renfufei@qq.com"> yF4HTML5中文学习网 - HTML5先行者学习网
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script> yF4HTML5中文学习网 - HTML5先行者学习网
<script> yF4HTML5中文学习网 - HTML5先行者学习网
// 参数,最大高度 yF4HTML5中文学习网 - HTML5先行者学习网
var MAX_HEIGHT = 100; yF4HTML5中文学习网 - HTML5先行者学习网
// 渲染 yF4HTML5中文学习网 - HTML5先行者学习网
function render(src){ yF4HTML5中文学习网 - HTML5先行者学习网
// 创建一个 Image 对象 yF4HTML5中文学习网 - HTML5先行者学习网
var image = new Image(); yF4HTML5中文学习网 - HTML5先行者学习网
// 绑定 load 事件处理器,加载完成后执行 yF4HTML5中文学习网 - HTML5先行者学习网
image.onload = function(){ yF4HTML5中文学习网 - HTML5先行者学习网
// 获取 canvas DOM 对象 yF4HTML5中文学习网 - HTML5先行者学习网
var canvas = document.getElementById("myCanvas"); yF4HTML5中文学习网 - HTML5先行者学习网
// 如果高度超标 yF4HTML5中文学习网 - HTML5先行者学习网
if(image.height > MAX_HEIGHT) { yF4HTML5中文学习网 - HTML5先行者学习网
// 宽度等比例缩放 *= yF4HTML5中文学习网 - HTML5先行者学习网
image.width *= MAX_HEIGHT / image.height; yF4HTML5中文学习网 - HTML5先行者学习网
image.height = MAX_HEIGHT; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
// 获取 canvas的 2d 环境对象, yF4HTML5中文学习网 - HTML5先行者学习网
// 可以理解Context是管理员,canvas是房子 yF4HTML5中文学习网 - HTML5先行者学习网
var ctx = canvas.getContext("2d"); yF4HTML5中文学习网 - HTML5先行者学习网
// canvas清屏 yF4HTML5中文学习网 - HTML5先行者学习网
ctx.clearRect(0, 0, canvas.width, canvas.height); yF4HTML5中文学习网 - HTML5先行者学习网
// 重置canvas宽高 yF4HTML5中文学习网 - HTML5先行者学习网
canvas.width = image.width; yF4HTML5中文学习网 - HTML5先行者学习网
canvas.height = image.height; yF4HTML5中文学习网 - HTML5先行者学习网
// 将图像绘制到canvas上 yF4HTML5中文学习网 - HTML5先行者学习网
ctx.drawImage(image, 0, 0, image.width, image.height); yF4HTML5中文学习网 - HTML5先行者学习网
// !!! 注意,image 没有加入到 dom之中 yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
// 设置src属性,浏览器会自动加载。 yF4HTML5中文学习网 - HTML5先行者学习网
// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。 yF4HTML5中文学习网 - HTML5先行者学习网
image.src = src; yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
// 加载 图像文件(url路径) yF4HTML5中文学习网 - HTML5先行者学习网
function loadImage(src){ yF4HTML5中文学习网 - HTML5先行者学习网
// 过滤掉 非 image 类型的文件 yF4HTML5中文学习网 - HTML5先行者学习网
if(!src.type.match(/image.*/)){ yF4HTML5中文学习网 - HTML5先行者学习网
if(window.console){ yF4HTML5中文学习网 - HTML5先行者学习网
console.log("选择的文件类型不是图片: ", src.type); yF4HTML5中文学习网 - HTML5先行者学习网
} else { yF4HTML5中文学习网 - HTML5先行者学习网
window.confirm("只能选择图片文件"); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
return; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
// 创建 FileReader 对象 并调用 render 函数来完成渲染. yF4HTML5中文学习网 - HTML5先行者学习网
var reader = new FileReader(); yF4HTML5中文学习网 - HTML5先行者学习网
// 绑定load事件自动回调函数 yF4HTML5中文学习网 - HTML5先行者学习网
reader.onload = function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// 调用前面的 render 函数 yF4HTML5中文学习网 - HTML5先行者学习网
render(e.target.result); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
// 读取文件内容 yF4HTML5中文学习网 - HTML5先行者学习网
reader.readAsDataURL(src); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
// 上传图片,jQuery版 yF4HTML5中文学习网 - HTML5先行者学习网
function sendImage(){ yF4HTML5中文学习网 - HTML5先行者学习网
// 获取 canvas DOM 对象 yF4HTML5中文学习网 - HTML5先行者学习网
var canvas = document.getElementById("myCanvas"); yF4HTML5中文学习网 - HTML5先行者学习网
// 获取Base64编码后的图像数据,格式是字符串 yF4HTML5中文学习网 - HTML5先行者学习网
// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。 yF4HTML5中文学习网 - HTML5先行者学习网
var dataurl = canvas.toDataURL("image/png"); yF4HTML5中文学习网 - HTML5先行者学习网
// 为安全 对URI进行编码 yF4HTML5中文学习网 - HTML5先行者学习网
// data%3Aimage%2Fpng%3Bbase64%2C 开头 yF4HTML5中文学习网 - HTML5先行者学习网
var imagedata = encodeURIComponent(dataurl); yF4HTML5中文学习网 - HTML5先行者学习网
//var url = $("#form").attr("action"); yF4HTML5中文学习网 - HTML5先行者学习网
// 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址 yF4HTML5中文学习网 - HTML5先行者学习网
// <input type="hidden" name="action" value="receive.jsp" /> yF4HTML5中文学习网 - HTML5先行者学习网
var url = $("input[name='action']").val(); yF4HTML5中文学习网 - HTML5先行者学习网
// 2. 也可以直接用某个dom对象的属性来获取 yF4HTML5中文学习网 - HTML5先行者学习网
// <input id="imageaction" type="hidden" action="receive.jsp"> yF4HTML5中文学习网 - HTML5先行者学习网
// var url = $("#imageaction").attr("action"); yF4HTML5中文学习网 - HTML5先行者学习网
// 因为是string,所以服务器需要对数据进行转码,写文件操作等。 yF4HTML5中文学习网 - HTML5先行者学习网
// 个人约定,所有http参数名字全部小写 yF4HTML5中文学习网 - HTML5先行者学习网
console.log(dataurl); yF4HTML5中文学习网 - HTML5先行者学习网
//console.log(imagedata); yF4HTML5中文学习网 - HTML5先行者学习网
var data = { yF4HTML5中文学习网 - HTML5先行者学习网
imagename: "myImage.png", yF4HTML5中文学习网 - HTML5先行者学习网
imagedata: imagedata yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
jQuery.ajax( { yF4HTML5中文学习网 - HTML5先行者学习网
url : url, yF4HTML5中文学习网 - HTML5先行者学习网
data : data, yF4HTML5中文学习网 - HTML5先行者学习网
type : "POST", yF4HTML5中文学习网 - HTML5先行者学习网
// 期待的返回值类型 yF4HTML5中文学习网 - HTML5先行者学习网
dataType: "json", yF4HTML5中文学习网 - HTML5先行者学习网
complete : function(xhr,result) { yF4HTML5中文学习网 - HTML5先行者学习网
//console.log(xhr.responseText); yF4HTML5中文学习网 - HTML5先行者学习网
var $tip2 = $("#tip2"); yF4HTML5中文学习网 - HTML5先行者学习网
if(!xhr){ yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text('网络连接失败!'); yF4HTML5中文学习网 - HTML5先行者学习网
return false; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
var text = xhr.responseText; yF4HTML5中文学习网 - HTML5先行者学习网
if(!text){ yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text('网络错误!'); yF4HTML5中文学习网 - HTML5先行者学习网
return false; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
var json = eval("("+text+")"); yF4HTML5中文学习网 - HTML5先行者学习网
if(!json){ yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text('解析错误!'); yF4HTML5中文学习网 - HTML5先行者学习网
return false; yF4HTML5中文学习网 - HTML5先行者学习网
} else { yF4HTML5中文学习网 - HTML5先行者学习网
$tip2.text(json.message); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
//console.dir(json); yF4HTML5中文学习网 - HTML5先行者学习网
//console.log(xhr.responseText); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
}); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
function init(){ yF4HTML5中文学习网 - HTML5先行者学习网
// 获取DOM元素对象 yF4HTML5中文学习网 - HTML5先行者学习网
var target = document.getElementById("drop-target"); yF4HTML5中文学习网 - HTML5先行者学习网
// 阻止 dragover(拖到DOM元素上方) 事件传递 yF4HTML5中文学习网 - HTML5先行者学习网
target.addEventListener("dragover", function(e){e.preventDefault();}, true); yF4HTML5中文学习网 - HTML5先行者学习网
// 拖动并放开鼠标的事件 yF4HTML5中文学习网 - HTML5先行者学习网
target.addEventListener("drop", function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// 阻止默认事件,以及事件传播 yF4HTML5中文学习网 - HTML5先行者学习网
e.preventDefault(); yF4HTML5中文学习网 - HTML5先行者学习网
// 调用前面的加载图像 函数,参数为dataTransfer对象的第一个文件 yF4HTML5中文学习网 - HTML5先行者学习网
loadImage(e.dataTransfer.files[0]); yF4HTML5中文学习网 - HTML5先行者学习网
}, true); yF4HTML5中文学习网 - HTML5先行者学习网
var setheight = document.getElementById("setheight"); yF4HTML5中文学习网 - HTML5先行者学习网
var maxheight = document.getElementById("maxheight"); yF4HTML5中文学习网 - HTML5先行者学习网
setheight.addEventListener("click", function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
var value = maxheight.value; yF4HTML5中文学习网 - HTML5先行者学习网
if(/^/d+$/.test(value)){ yF4HTML5中文学习网 - HTML5先行者学习网
MAX_HEIGHT = parseInt(value); yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
e.preventDefault(); yF4HTML5中文学习网 - HTML5先行者学习网
},true); yF4HTML5中文学习网 - HTML5先行者学习网
var btnsend = document.getElementById("btnsend"); yF4HTML5中文学习网 - HTML5先行者学习网
btnsend.addEventListener("click", function(e){ yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
sendImage(); yF4HTML5中文学习网 - HTML5先行者学习网
},true); yF4HTML5中文学习网 - HTML5先行者学习网
}; yF4HTML5中文学习网 - HTML5先行者学习网
window.addEventListener("DOMContentLoaded", function() { yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
init(); yF4HTML5中文学习网 - HTML5先行者学习网
},false); yF4HTML5中文学习网 - HTML5先行者学习网
</script> yF4HTML5中文学习网 - HTML5先行者学习网
</head> yF4HTML5中文学习网 - HTML5先行者学习网
<body> yF4HTML5中文学习网 - HTML5先行者学习网
<div> yF4HTML5中文学习网 - HTML5先行者学习网
<h1>通过Canvas及File API缩放并上传图片</h1> yF4HTML5中文学习网 - HTML5先行者学习网
<p>从文件夹拖动一张照片到下方的盒子里, canvas 和 JavaScript将会自动的进行缩放.</p> yF4HTML5中文学习网 - HTML5先行者学习网
<div> yF4HTML5中文学习网 - HTML5先行者学习网
<input type="text" id="maxheight" value="100"/> yF4HTML5中文学习网 - HTML5先行者学习网
<button id="setheight">设置图片最大高度</button> yF4HTML5中文学习网 - HTML5先行者学习网
<input type="hidden" name="action" value="receive.jsp" /> yF4HTML5中文学习网 - HTML5先行者学习网
</div> yF4HTML5中文学习网 - HTML5先行者学习网
<div id="preview-row"> yF4HTML5中文学习网 - HTML5先行者学习网
<div id="drop-target" style="width:400px;height:200px;min-height:100px;min-width:200px;background:#eee;cursor:pointer;">拖动图片文件到这里...</div> yF4HTML5中文学习网 - HTML5先行者学习网
<div> yF4HTML5中文学习网 - HTML5先行者学习网
<div> yF4HTML5中文学习网 - HTML5先行者学习网
<button id="btnsend"> 上 传 </button> <span id="tip2" style="padding:8px 0;color:#f00;"></span> yF4HTML5中文学习网 - HTML5先行者学习网
</div> yF4HTML5中文学习网 - HTML5先行者学习网
</div> yF4HTML5中文学习网 - HTML5先行者学习网
<div><h4>缩略图:</h4></div> yF4HTML5中文学习网 - HTML5先行者学习网
<div id="preview" style="background:#f4f4f4;width:400px;height:200px;min-height:100px;min-width:200px;"> yF4HTML5中文学习网 - HTML5先行者学习网
<canvas id="myCanvas"></canvas> yF4HTML5中文学习网 - HTML5先行者学习网
</div> yF4HTML5中文学习网 - HTML5先行者学习网
</div> yF4HTML5中文学习网 - HTML5先行者学习网
</div> yF4HTML5中文学习网 - HTML5先行者学习网
</body> yF4HTML5中文学习网 - HTML5先行者学习网
</html> yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网服务端页面,receive.jsp
yF4HTML5中文学习网 - HTML5先行者学习网 yF4HTML5中文学习网 - HTML5先行者学习网
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> yF4HTML5中文学习网 - HTML5先行者学习网
<%@page import="sun.misc.BASE64Decoder"%> yF4HTML5中文学习网 - HTML5先行者学习网
<%@page import="java.io.*"%> yF4HTML5中文学习网 - HTML5先行者学习网
<%@page import="org.springframework.web.util.UriComponents"%> yF4HTML5中文学习网 - HTML5先行者学习网
<%@page import="java.net.URLDecoder"%> yF4HTML5中文学习网 - HTML5先行者学习网
<%! yF4HTML5中文学习网 - HTML5先行者学习网
// 本文件:/receive.jsp yF4HTML5中文学习网 - HTML5先行者学习网
// 图片存放路径 yF4HTML5中文学习网 - HTML5先行者学习网
String photoPath = "D:/blog/upload/photo/"; yF4HTML5中文学习网 - HTML5先行者学习网
File photoPathFile = new File(photoPath); yF4HTML5中文学习网 - HTML5先行者学习网
// references: http://blog.csdn.net/remote_roamer/article/details/2979822 yF4HTML5中文学习网 - HTML5先行者学习网
private boolean saveImageToDisk(byte[] data,String imageName) throws IOException{ yF4HTML5中文学习网 - HTML5先行者学习网
int len = data.length; yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
// 写入到文件 yF4HTML5中文学习网 - HTML5先行者学习网
FileOutputStream outputStream = new FileOutputStream(new File(photoPathFile,imageName)); yF4HTML5中文学习网 - HTML5先行者学习网
outputStream.write(data); yF4HTML5中文学习网 - HTML5先行者学习网
outputStream.flush(); yF4HTML5中文学习网 - HTML5先行者学习网
outputStream.close(); yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
return true; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
private byte[] decode(String imageData) throws IOException{ yF4HTML5中文学习网 - HTML5先行者学习网
BASE64Decoder decoder = new BASE64Decoder(); yF4HTML5中文学习网 - HTML5先行者学习网
byte[] data = decoder.decodeBuffer(imageData); yF4HTML5中文学习网 - HTML5先行者学习网
for(int i=0;i<data.length;++i) yF4HTML5中文学习网 - HTML5先行者学习网
{ yF4HTML5中文学习网 - HTML5先行者学习网
if(data[i]<0) yF4HTML5中文学习网 - HTML5先行者学习网
{ yF4HTML5中文学习网 - HTML5先行者学习网
//调整异常数据 yF4HTML5中文学习网 - HTML5先行者学习网
data[i]+=256; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
return data; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
%> yF4HTML5中文学习网 - HTML5先行者学习网
<% yF4HTML5中文学习网 - HTML5先行者学习网
String path = request.getContextPath(); yF4HTML5中文学习网 - HTML5先行者学习网
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; yF4HTML5中文学习网 - HTML5先行者学习网
%> yF4HTML5中文学习网 - HTML5先行者学习网
<% yF4HTML5中文学习网 - HTML5先行者学习网
//如果是IE,那么需要设置为text/html,否则会弹框下载 yF4HTML5中文学习网 - HTML5先行者学习网
//response.setContentType("text/html;charset=UTF-8"); yF4HTML5中文学习网 - HTML5先行者学习网
response.setContentType("application/json;charset=UTF-8"); yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
String imageName = request.getParameter("imagename"); yF4HTML5中文学习网 - HTML5先行者学习网
String imageData = request.getParameter("imagedata"); yF4HTML5中文学习网 - HTML5先行者学习网
int success = 0; yF4HTML5中文学习网 - HTML5先行者学习网
String message = ""; yF4HTML5中文学习网 - HTML5先行者学习网
if(null == imageData || imageData.length() < 100){ yF4HTML5中文学习网 - HTML5先行者学习网
// 数据太短,明显不合理 yF4HTML5中文学习网 - HTML5先行者学习网
message = "上传失败,数据太短或不存在"; yF4HTML5中文学习网 - HTML5先行者学习网
} else { yF4HTML5中文学习网 - HTML5先行者学习网
// 去除开头不合理的数据 yF4HTML5中文学习网 - HTML5先行者学习网
imageData = imageData.substring(30); yF4HTML5中文学习网 - HTML5先行者学习网
imageData = URLDecoder.decode(imageData,"UTF-8"); yF4HTML5中文学习网 - HTML5先行者学习网
//System.out.println(imageData); yF4HTML5中文学习网 - HTML5先行者学习网
byte[] data = decode(imageData); yF4HTML5中文学习网 - HTML5先行者学习网
int len = data.length; yF4HTML5中文学习网 - HTML5先行者学习网
int len2 = imageData.length(); yF4HTML5中文学习网 - HTML5先行者学习网
if(null == imageName || imageName.length() < 1){ yF4HTML5中文学习网 - HTML5先行者学习网
imageName = System.currentTimeMillis()+".png"; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
saveImageToDisk(data,imageName); yF4HTML5中文学习网 - HTML5先行者学习网
// yF4HTML5中文学习网 - HTML5先行者学习网
success = 1; yF4HTML5中文学习网 - HTML5先行者学习网
message = "上传成功,参数长度:"+len2+"字符,解析文件大小:"+len+"字节"; yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
// 后台打印 yF4HTML5中文学习网 - HTML5先行者学习网
System.out.println("message="+message); yF4HTML5中文学习网 - HTML5先行者学习网
%> yF4HTML5中文学习网 - HTML5先行者学习网
{ yF4HTML5中文学习网 - HTML5先行者学习网
"message": "<%=message %>", yF4HTML5中文学习网 - HTML5先行者学习网
"success": <%=success %> yF4HTML5中文学习网 - HTML5先行者学习网
} yF4HTML5中文学习网 - HTML5先行者学习网
yF4HTML5中文学习网 - HTML5先行者学习网