文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么通过Canvas及File API缩放并上传图片

2024-04-02 19:55

关注

本文小编为大家详细介绍“怎么通过Canvas及File API缩放并上传图片”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么通过Canvas及File API缩放并上传图片”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

代码如下:

// 参数,最大高度

var MAX_HEIGHT = 100;

// 渲染

function render(src){

// 创建一个 Image 对象

var image = new Image();

// 绑定 load 事件处理器,加载完成后执行

image.onload = function(){

// 获取 canvas DOM 对象

var canvas = document.getElementById("myCanvas");

// 如果高度超标

if(image.height > MAX_HEIGHT) {

// 宽度等比例缩放 *=

image.width *= MAX_HEIGHT / image.height;

image.height = MAX_HEIGHT;

}

// 获取 canvas的 2d 环境对象,

// 可以理解Context是管理员,canvas是房子

var ctx = canvas.getContext("2d");

// canvas清屏

ctx.clearRect(0, 0, canvas.width, canvas.height);

// 重置canvas宽高

canvas.width = image.width;

canvas.height = image.height;

// 将图像绘制到canvas上

ctx.drawImage(image, 0, 0, image.width, image.height);

// !!! 注意,image 没有加入到 dom之中

};

// 设置src属性,浏览器会自动加载。

// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。

image.src = src;

};

在上面的例子中,你可以使用canvas 的 toDataURL() 方法获取图像的 Base64编码的值(可以类似理解为16进制字符串,或者二进制数据流).

注意: canvas 的 toDataURL() 获取的URL以字符串开头,有22个无用的数据 "data:image/png;base64,",需要在客户端或者服务端进行过滤.

原则上只要浏览器支持,URL地址的长度是没有限制的,而1024的长度限制,是老一代IE所独有的。

请问,如何获取我们需要的图像呢?

好孩子,很高兴你能这么问。你并不能通过File 输入框来直接处理,你从这个文件输入框元素所能获取的仅仅是用户所选择文件的path路径。按照常规想象,你可以通过这个path路径信息来加载图像,但是,在浏览器里面这是不现实的。(译者注:浏览器厂商必须保证自己的浏览器绝对安全,才能获得市场,至少避免媒体的攻击,如果允许这样做,那恶意网址可以通过拼凑文件路径来尝试获取某些敏感信息).

为了实现这个需求,我们可以使用HTML5的File API 来读取用户磁盘上的文件,并用这个file来作为图像的源(src,source).

File API简介

新的File API接口是在不违背任何安全沙盒规则下,读取和列出用户文件目录的一个途径—— 通过沙盒(sandbox)限制,恶意网站并不能将病毒写入用户磁盘,当然更不能执行。

我们要使用的文件读取对象叫做 FileReader,FileReader允许开发者读取文件的内容(具体浏览器的实现方式可能大不相同)。

假设我们已经获取了图像文件的path路径,那么依赖前面的代码,使用FileReader来加载和渲染图像就变得很容易了:

复制代码

代码如下:

// 加载 图像文件(url路径)

function loadImage(src){

// 过滤掉 非 image 类型的文件

if(!src.type.match(/image.*/)){

if(window.console){

console.log("选择的文件类型不是图片: ", src.type);

} else {

window.confirm("只能选择图片文件");

}

return;

}

// 创建 FileReader 对象 并调用 render 函数来完成渲染.

var reader = new FileReader();

// 绑定load事件自动回调函数

reader.onload = function(e){

// 调用前面的 render 函数

render(e.target.result);

};

// 读取文件内容

reader.readAsDataURL(src);

};

请问,如何获取文件呢?

小白兔,要有耐心!我们的下一步就是获取文件,当然有好多方法可以实现啦。例如:你可以用文本框让用户输入文件路径,但很显然大多数用户都不是开发者,对输入什么值根本就不了解.

为了用户使用方便,我们采用 Drag and Drop API接口。

使用 Drag and Drop API

拖拽接口(Drag and Drop)非常简单——在大多数的DOM元素上,你都可以通过绑定事件处理器来实现. 只要用户从磁盘上拖动一个文件到dom对象上并放开鼠标,那我们就可以读取这个文件。代码如下:

复制代码

代码如下:

function init(){

// 获取DOM元素对象

var target = document.getElementById("drop-target");

// 阻止 dragover(拖到DOM元素上方) 事件传递

target.addEventListener("dragover", function(e){e.preventDefault();}, true);

// 拖动并放开鼠标的事件

target.addEventListener("drop", function(e){

// 阻止默认事件,以及事件传播

e.preventDefault();

// 调用前面的加载图像 函数,参数为dataTransfer对象的第一个文件

loadImage(e.dataTransfer.files[0]);

}, true);

var setheight = document.getElementById("setheight");

var maxheight = document.getElementById("maxheight");

setheight.addEventListener("click", function(e){

//

var value = maxheight.value;

if(/^/d+$/.test(value)){

MAX_HEIGHT = parseInt(value);

}

e.preventDefault();

},true);

var btnsend = document.getElementById("btnsend");

btnsend.addEventListener("click", function(e){

//

sendImage();

},true);

};

我们还可以做一些其他的处理,比如显示预览图。但如果不想压缩图片的话,那很可能没什么用。我们将采用Ajax通过HTTP 的post方式上传图片数据。下面的例子是使用Dojo框架来完成请求的,当然你也可以采用其他的Ajax技术来实现.

Dojo 代码如下:

复制代码

代码如下:

// 译者并不懂Dojo,所以将在后面附上jQuery的实现

// Remember that DTK 1.7+ is AMD!

require(["dojo/request"], function(request){

// 设置请求URL,参数,以及回调。

request.post("image-handler.php", {

data: {

imageName: "myImage.png",

imageData: encodeURIComponent(document.getElementById("canvas").toDataURL("image/png"))

}

}).then(function(text){

console.log("The server returned: ", text);

});

});

jQuery 实现如下:

复制代码

代码如下:

// 上传图片,jQuery版

function sendImage(){

// 获取 canvas DOM 对象

var canvas = document.getElementById("myCanvas");

// 获取Base64编码后的图像数据,格式是字符串

// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。

var dataurl = canvas.toDataURL("image/png");

// 为安全 对URI进行编码

// data%3Aimage%2Fpng%3Bbase64%2C 开头

var imagedata = encodeURIComponent(dataurl);

//var url = $("#form").attr("action");

// 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址

// <input type="hidden" name="action" value="receive.jsp" />

var url = $("input[name='action']").val();

// 2. 也可以直接用某个dom对象的属性来获取

// <input id="imageaction" type="hidden" action="receive.jsp">

// var url = $("#imageaction").attr("action");

// 因为是string,所以服务器需要对数据进行转码,写文件操作等。

// 个人约定,所有http参数名字全部小写

console.log(dataurl);

//console.log(imagedata);

var data = {

imagename: "myImage.png",

imagedata: imagedata

};

jQuery.ajax( {

url : url,

data : data,

type : "POST",

// 期待的返回值类型

dataType: "json",

complete : function(xhr,result) {

//console.log(xhr.responseText);

var $tip2 = $("#tip2");

if(!xhr){

$tip2.text('网络连接失败!');

return false;

}

var text = xhr.responseText;

if(!text){

$tip2.text('网络错误!');

return false;

}

var json = eval("("+text+")");

if(!json){

$tip2.text('解析错误!');

return false;

} else {

$tip2.text(json.message);

}

//console.dir(json);

//console.log(xhr.responseText);

}

});

};

OK,搞定!你还需要做的,就是创建一个只管的用户界面,并允许你控制图片的大小。上传到服务器端的数据,并不需要处理enctype为 multi-part/form-data 的情况,仅仅一个简单的POST表单处理程序就可以了.

好了,下面附上完整的代码示例:

复制代码

代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<!DOCTYPE html>

<html>

<head>

<title>通过Canvas及File API缩放并上传图片</title>

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">

<meta http-equiv="keywords" content="Canvas,File,Image">

<meta http-equiv="description" content="2013年8月8日,renfufei@qq.com">

<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

<script>

// 参数,最大高度

var MAX_HEIGHT = 100;

// 渲染

function render(src){

// 创建一个 Image 对象

var image = new Image();

// 绑定 load 事件处理器,加载完成后执行

image.onload = function(){

// 获取 canvas DOM 对象

var canvas = document.getElementById("myCanvas");

// 如果高度超标

if(image.height > MAX_HEIGHT) {

// 宽度等比例缩放 *=

image.width *= MAX_HEIGHT / image.height;

image.height = MAX_HEIGHT;

}

// 获取 canvas的 2d 环境对象,

// 可以理解Context是管理员,canvas是房子

var ctx = canvas.getContext("2d");

// canvas清屏

ctx.clearRect(0, 0, canvas.width, canvas.height);

// 重置canvas宽高

canvas.width = image.width;

canvas.height = image.height;

// 将图像绘制到canvas上

ctx.drawImage(image, 0, 0, image.width, image.height);

// !!! 注意,image 没有加入到 dom之中

};

// 设置src属性,浏览器会自动加载。

// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。

image.src = src;

};

// 加载 图像文件(url路径)

function loadImage(src){

// 过滤掉 非 image 类型的文件

if(!src.type.match(/image.*/)){

if(window.console){

console.log("选择的文件类型不是图片: ", src.type);

} else {

window.confirm("只能选择图片文件");

}

return;

}

// 创建 FileReader 对象 并调用 render 函数来完成渲染.

var reader = new FileReader();

// 绑定load事件自动回调函数

reader.onload = function(e){

// 调用前面的 render 函数

render(e.target.result);

};

// 读取文件内容

reader.readAsDataURL(src);

};

// 上传图片,jQuery版

function sendImage(){

// 获取 canvas DOM 对象

var canvas = document.getElementById("myCanvas");

// 获取Base64编码后的图像数据,格式是字符串

// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。

var dataurl = canvas.toDataURL("image/png");

// 为安全 对URI进行编码

// data%3Aimage%2Fpng%3Bbase64%2C 开头

var imagedata = encodeURIComponent(dataurl);

//var url = $("#form").attr("action");

// 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址

// <input type="hidden" name="action" value="receive.jsp" />

var url = $("input[name='action']").val();

// 2. 也可以直接用某个dom对象的属性来获取

// <input id="imageaction" type="hidden" action="receive.jsp">

// var url = $("#imageaction").attr("action");

// 因为是string,所以服务器需要对数据进行转码,写文件操作等。

// 个人约定,所有http参数名字全部小写

console.log(dataurl);

//console.log(imagedata);

var data = {

imagename: "myImage.png",

imagedata: imagedata

};

jQuery.ajax( {

url : url,

data : data,

type : "POST",

// 期待的返回值类型

dataType: "json",

complete : function(xhr,result) {

//console.log(xhr.responseText);

var $tip2 = $("#tip2");

if(!xhr){

$tip2.text('网络连接失败!');

return false;

}

var text = xhr.responseText;

if(!text){

$tip2.text('网络错误!');

return false;

}

var json = eval("("+text+")");

if(!json){

$tip2.text('解析错误!');

return false;

} else {

$tip2.text(json.message);

}

//console.dir(json);

//console.log(xhr.responseText);

}

});

};

function init(){

// 获取DOM元素对象

var target = document.getElementById("drop-target");

// 阻止 dragover(拖到DOM元素上方) 事件传递

target.addEventListener("dragover", function(e){e.preventDefault();}, true);

// 拖动并放开鼠标的事件

target.addEventListener("drop", function(e){

// 阻止默认事件,以及事件传播

e.preventDefault();

// 调用前面的加载图像 函数,参数为dataTransfer对象的第一个文件

loadImage(e.dataTransfer.files[0]);

}, true);

var setheight = document.getElementById("setheight");

var maxheight = document.getElementById("maxheight");

setheight.addEventListener("click", function(e){

//

var value = maxheight.value;

if(/^/d+$/.test(value)){

MAX_HEIGHT = parseInt(value);

}

e.preventDefault();

},true);

var btnsend = document.getElementById("btnsend");

btnsend.addEventListener("click", function(e){

//

sendImage();

},true);

};

window.addEventListener("DOMContentLoaded", function() {

//

init();

},false);

</script>

</head>

<body>

<div>

<h2>通过Canvas及File API缩放并上传图片</h2>

<p>从文件夹拖动一张照片到下方的盒子里, canvas 和 JavaScript将会自动的进行缩放.</p>

<div>

<input type="text" id="maxheight" value="100"/>

<button id="setheight">设置图片最大高度</button>

<input type="hidden" name="action" value="receive.jsp" />

</div>

<div id="preview-row">

<div id="drop-target" style="width:400px;height:200px;min-height:100px;min-width:200px;background:#eee;cursor:pointer;">拖动图片文件到这里...</div>

<div>

<div>

<button id="btnsend"> 上 传 </button> <span id="tip2" style="padding:8px 0;color:#f00;"></span>

</div>

</div>

<div><h5>缩略图:</h5></div>

<div id="preview" style="background:#f4f4f4;width:400px;height:200px;min-height:100px;min-width:200px;">

<canvas id="myCanvas"></canvas>

</div>

</div>

</div>

</body>

</html>

服务端页面,receive.jsp

复制代码

代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@page import="sun.misc.BASE64Decoder"%>

<%@page import="java.io.*"%>

<%@page import="org.springframework.web.util.UriComponents"%>

<%@page import="java.net.URLDecoder"%>

<%!

// 本文件:/receive.jsp

// 图片存放路径

String photoPath = "D:/blog/upload/photo/";

File photoPathFile = new File(photoPath);

// references: http://blog.csdn.net/remote_roamer/article/details/2979822

private boolean saveImageToDisk(byte[] data,String imageName) throws IOException{

int len = data.length;

//

// 写入到文件

FileOutputStream outputStream = new FileOutputStream(new File(photoPathFile,imageName));

outputStream.write(data);

outputStream.flush();

outputStream.close();

//

return true;

}

private byte[] decode(String imageData) throws IOException{

BASE64Decoder decoder = new BASE64Decoder();

byte[] data = decoder.decodeBuffer(imageData);

for(int i=0;i<data.length;++i)

{

if(data[i]<0)

{

//调整异常数据

data[i]+=256;

}

}

//

return data;

}

%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<%

//如果是IE,那么需要设置为text/html,否则会弹框下载

//response.setContentType("text/html;charset=UTF-8");

response.setContentType("application/json;charset=UTF-8");

//

String imageName = request.getParameter("imagename");

String imageData = request.getParameter("imagedata");

int success = 0;

String message = "";

if(null == imageData || imageData.length() < 100){

// 数据太短,明显不合理

message = "上传失败,数据太短或不存在";

} else {

// 去除开头不合理的数据

imageData = imageData.substring(30);

imageData = URLDecoder.decode(imageData,"UTF-8");

//System.out.println(imageData);

byte[] data = decode(imageData);

int len = data.length;

int len2 = imageData.length();

if(null == imageName || imageName.length() < 1){

imageName = System.currentTimeMillis()+".png";

}

saveImageToDisk(data,imageName);

//

success = 1;

message = "上传成功,参数长度:"+len2+"字符,解析文件大小:"+len+"字节";

}

// 后台打印

System.out.println("message="+message);

%>

{

"message": "<%=message %>",

"success": <%=success %>

}

读到这里,这篇“怎么通过Canvas及File API缩放并上传图片”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯