Home >Web Front-end >H5 Tutorial >Complete example of zooming and uploading images through Canvas and File API_html5 tutorial skills

Complete example of zooming and uploading images through Canvas and File API_html5 tutorial skills

WBOY
WBOYOriginal
2016-05-16 15:49:071595browse

Example address: Canvas Resize Demo
Original author: Dr. Tom Trenka
Original date: August 6, 2013
Translation date: August 8, 2013

Tom Trenka It is a huge honor for me to write an article for "my" blog. Tom was one of the original contributors to the Dojo framework and was my mentor at SitePen. I witnessed his genius at the highest level, and he was always the first to foresee many difficult problems with forward-looking solutions. He always thinks from the outside and solves fringe problems in an unconventional but solid way. This article is a perfect example.
Lately I've been asked a lot about creating a user interface API that would allow users to upload images to a server (among other things) and be used on the client side of the large number of websites our company supports. Usually this is a very easy thing - create a form, add a file type input box, let the user select an image from the computer, and set the enctype="multipart/form-data" form on the form tag properties and then upload. Pretty simple, isn't it? In fact, here is a simple enough example; Click to enter
But what if you want to pre-process the image in some way before uploading it? For example, you must compress the image size first, or you need the image to be in only certain types of formats, such as png or jpg, what should you do?
Use canvas to solve it!

Introduction to Canvas
Canvas is a new DOM element in HTML5 that allows users to draw graphics directly on the page, usually using JavaScript. Different format standards are also different. For example, SVG is a raster API (raster API) while VML is a vector API. You can consider using Adobe Illustrator (vector) for drawing and Adobe Photoshop (raster) for drawing. difference.

What you can do on canvas is to read and render images, and allow you to manipulate image data through JavaScript. There are many existing articles that demonstrate basic image processing for you - focusing mainly on various image filtering techniques - but all we need is to scale the image and convert it to a specific file format, and Canvas can do these things completely.

Our assumed requirements, such as the image height not exceeding 100 pixels, no matter how high the original image is. The basic code is as follows:

Copy the code
The code is as follows:

// Parameters, maximum height
var MAX_HEIGHT = 100;
// Rendering
function render(src){
// Create an Image object
var image = new Image();
// Bind the load event handler and execute after loading is completed
image.onload = function(){
// Get the canvas DOM object
var canvas = document.getElementById("myCanvas");
// If the height exceeds the standard
if(image.height > MAX_HEIGHT) {
// Width proportional scaling *=
image.width *= MAX_HEIGHT / image.height;
image.height = MAX_HEIGHT;
}
// Get the 2d environment object of canvas,
// It can be understood that Context is the administrator and canvas is the house
var ctx = canvas.getContext("2d");
//Clear canvas screen
ctx.clearRect(0, 0, canvas.width, canvas.height);
//Reset canvas width and height
canvas.width = image.width;
canvas.height = image.height;
// Draw the image onto the canvas
ctx.drawImage(image, 0, 0, image.width, image.height);
// !!! Note that the image is not added to the dom
};
// Set the src attribute and the browser will automatically load it.
// Remember that the event must be bound first before the src attribute can be set, otherwise synchronization problems will occur.
image.src = src;
};

In the above example, you can use canvas's toDataURL() method to obtain the Base64-encoded value of the image (which can be similarly understood as a hexadecimal string, or binary data stream).
Note: canvas's toDataURL () The obtained URL starts with a string and has 22 useless data "data:image/png;base64," which needs to be filtered on the client or server.
In principle, as long as the browser supports it, the URL address There is no limit to the length, and the length limit of 1024 is unique to the older generation of IE.

Excuse me, how to get the images we need?
Good boy, I’m glad you asked. You cannot process it directly through the File input box. All you can get from this file input box element is only the path to the file selected by the user. According to conventional imagination, you can load images through this path path information, but this is unrealistic in the browser. (Translator's note: Browser manufacturers must ensure that their browsers are absolutely secure in order to gain market share and at least avoid media attacks. If this is allowed, malicious URLs can try to obtain certain sensitive information by piecing together file paths).
In order to achieve this requirement, we can use HTML5's File API to read files on the user's disk and use this file as the source of the image (src, source).

File API Introduction
The new File API interface is a way to read and list user file directories without violating any security sandbox rules - through sandbox restrictions, malicious websites cannot write viruses. User disks, of course, cannot be executed.
The file reading object we want to use is called FileReader. FileReader allows developers to read the contents of files (the implementation of specific browsers may be very different).

Assuming that we have obtained the path path of the image file, then relying on the previous code, it becomes easy to use FileReader to load and render the image:

Copy code
The code is as follows:

// Load image file (url path)
function loadImage(src){
/ / Filter out non-image type files
if(!src.type.match(/image.*/)){
if(window.console){
console.log("Selected file type Not a picture: ", src.type);
} else {
window.confirm("Only picture files can be selected");
}
return;
}
// Create a FileReader object and call the render function to complete rendering.
var reader = new FileReader();
// Bind the load event automatic callback function
reader.onload = function(e){
/ / Call the previous render function
render(e.target.result);
};
// Read the file content
reader.readAsDataURL(src);
};

Excuse me, how to obtain the file?
Little white rabbit, be patient! Our next step is to obtain the file, and of course there are many ways to do this. For example: you can use a text box to allow users to enter file paths, but obviously most users are not developers and have no idea what values ​​to enter.
For user convenience, we use the Drag and Drop API interface.

Using the Drag and Drop API
The drag and drop interface (Drag and Drop) is very simple - on most DOM elements, you can bind event handlers to Implementation. As long as the user drags a file from the disk to the dom object and releases the mouse, we can read the file. The code is as follows:

Copy code
The code is as follows:

function init(){
// Get the DOM element object
var target = document.getElementById("drop-target");
// Prevent dragover (drag above the DOM element) event delivery
target.addEventListener("dragover ", function(e){e.preventDefault();}, true);
// Drag and release the mouse event
target.addEventListener("drop", function(e){
// Prevent default events and event propagation
e.preventDefault();
// Call the previous load image function, the parameter is the first file of the dataTransfer object
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);
};

We can also do some other processing, such as displaying preview images. But if you don't want to compress the image, it's probably useless. We will use Ajax to upload image data through HTTP post method. The following example uses the Dojo framework to complete the request. Of course, you can also use other Ajax technologies to implement it.
Dojo code is as follows:

Copy Code
The code is as follows:

// The translator does not understand Dojo, so the jQuery implementation will be attached later
// Remember that DTK 1.7 is AMD!
require(["dojo/request"], function(request){
// Set the request URL, parameters, and callbacks.
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 is implemented as follows :

Copy code
The code is as follows:

// Upload image, jQuery version
function sendImage(){
// Get the canvas DOM object
var canvas = document.getElementById("myCanvas");
// Get the Base64 encoded image data, the format is a string
// At the beginning of "data:image/png;base64,", it needs to be removed on the client or server side, and the following parts can be written directly to the file.
var dataurl = canvas.toDataURL("image/png");
// Encode URI for security
// data:image/png;base64, beginning
var imagedata = encodeURIComponent( dataurl);
//var url = $("#form").attr("action");
// 1. If the form is difficult to process, you can use a hidden hidden field to set the request Address
//
var url = $("input[name='action']").val ();
// 2. You can also directly use the attributes of a DOM object to obtain
//
// var url = $("#imageaction").attr("action");
// Because it is a string, the server needs to transcode the data, write file operations, etc.
// Personal agreement, all http parameter names are in lowercase
console.log(dataurl);
//console.log(imagedata);
var data = {
imagename: "myImage .png",
imagedata: imagedata
};
jQuery.ajax( {
url : url,
data : data,
type : "POST",
/ / Expected return value type
dataType: "json",
complete : function(xhr,result) {
//console.log(xhr.responseText);
var $tip2 = $( "#tip2");
if(!xhr){
$tip2.text('Network connection failed!');
return false;
}
var text = xhr.responseText ;
if(!text){
$tip2.text('Network error!');
return false;
}
var json = eval("(" text ")" );
if(!json){
$tip2.text('Parse error!');
return false;
} else {
$tip2.text(json.message) ;
}
//console.dir(json);
//console.log(xhr.responseText);
}
});
};

OK, done! All you need to do is create a simple user interface that allows you to control the size of the image. The data uploaded to the server does not need to handle the enctype of multi-part/form-data. Just a simple POST form handler is enough.
Okay, here is a complete code example:

Copy code
The code is as follows:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() "://" request.getServerName() ":" request.getServerPort() path "/";
%>



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






<script> <br>// 参数,最大高度 <br>var MAX_HEIGHT = 100; <br>// 渲染 <br>function render(src){ <br>// 创建一个 Image 对象 <br>var image = new Image(); <br>// 绑定 load 事件处理器,加载完成后执行 <br>image.onload = function(){ <br>// 获取 canvas DOM 对象 <br>var canvas = document.getElementById("myCanvas"); <br>// 如果高度超标 <br>if(image.height > MAX_HEIGHT) { <br>// 宽度等比例缩放 *= <br>image.width *= MAX_HEIGHT / image.height; <br>image.height = MAX_HEIGHT; <br>} <br>// 获取 canvas的 2d 环境对象, <br>// 可以理解Context是管理员,canvas是房子 <br>var ctx = canvas.getContext("2d"); <br>// canvas清屏 <br>ctx.clearRect(0, 0, canvas.width, canvas.height); <br>// 重置canvas宽高 <br>canvas.width = image.width; <br>canvas.height = image.height; <br>// 将图像绘制到canvas上 <br>ctx.drawImage(image, 0, 0, image.width, image.height); <br>// !!! 注意,image 没有加入到 dom之中 <br>}; <br>// 设置src属性,浏览器会自动加载。 <br>// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。 <br>image.src = src; <br>}; <br>// 加载 图像文件(url路径) <br>function loadImage(src){ <br>// 过滤掉 非 image 类型的文件 <br>if(!src.type.match(/image.*/)){ <br>if(window.console){ <br>console.log("选择的文件类型不是图片: ", src.type); <br>} else { <br>window.confirm("只能选择图片文件"); <br>} <br>return; <br>} <br>// 创建 FileReader 对象 并调用 render 函数来完成渲染. <br>var reader = new FileReader(); <br>// 绑定load事件自动回调函数 <br>reader.onload = function(e){ <br>// 调用前面的 render 函数 <br>render(e.target.result); <br>}; <br>// 读取文件内容 <br>reader.readAsDataURL(src); <br>}; <br>// 上传图片,jQuery版 <br>function sendImage(){ <br>// 获取 canvas DOM 对象 <br>var canvas = document.getElementById("myCanvas"); <br>// 获取Base64编码后的图像数据,格式是字符串 <br>// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后面的部分可以直接写入文件。 <br>var dataurl = canvas.toDataURL("image/png"); <br>// 为安全 对URI进行编码 <br>// data:image/png;base64, 开头 <br>var imagedata = encodeURIComponent(dataurl); <br>//var url = $("#form").attr("action"); <br>// 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址 <br>// <input type="hidden" name="action" value="receive.jsp" /> <br>var url = $("input[name='action']").val(); <br>// 2. 也可以直接用某个dom对象的属性来获取 <br>// <input id="imageaction" type="hidden" action="receive.jsp"> <br>// var url = $("#imageaction").attr("action"); <br>// 因为是string,所以服务器需要对数据进行转码,写文件操作等。 <br>// 个人约定,所有http参数名字全部小写 <br>console.log(dataurl); <br>//console.log(imagedata); <br>var data = { <br>imagename: "myImage.png", <br>imagedata: imagedata <br>}; <br>jQuery.ajax( { <br>url : url, <br>data : data, <br>type : "POST", <br>// 期待的返回值类型 <br>dataType: "json", <br>complete : function(xhr,result) { <br>//console.log(xhr.responseText); <br>var $tip2 = $("#tip2"); <br>if(!xhr){ <br>$tip2.text('网络连接失败!'); <br>return false; <br>} <br>var text = xhr.responseText; <br>if(!text){ <br>$tip2.text('网络错误!'); <br>return false; <br>} <br>var json = eval("(" text ")"); <br>if(!json){ <br>$tip2.text('解析错误!'); <br>return false; <br>} else { <br>$tip2.text(json.message); <br>} <br>//console.dir(json); <br>//console.log(xhr.responseText); <br>} <br>}); <br>}; <br>function init(){ <br>// 获取DOM元素对象 <br>var target = document.getElementById("drop-target"); <br>// Prevent dragover (drag above DOM element) event delivery <br>target.addEventListener("dragover", function(e){e.preventDefault( );}, true); <br>// Drag and release the mouse event<br>target.addEventListener("drop", function(e){ <br>// Prevent default events and event propagation<br>e.preventDefault(); <br>// Call the previous load image function, the parameter is the first file of the dataTransfer object <br>loadImage(e.dataTransfer.files[0]); <br>}, true) ; <br>var setheight = document.getElementById("setheight"); <br>var maxheight = document.getElementById("maxheight"); <br>setheight.addEventListener("click", function(e){ <br> // <br>var value = maxheight.value; <br>if(/^d $/.test(value)){ <br>MAX_HEIGHT = parseInt(value); <br>} <br>e.preventDefault( ); <br>},true); <br>var btnsend = document.getElementById("btnsend"); <br>btnsend.addEventListener("click", function(e){ <br>// <br>sendImage (); <br>},true); <br>}; <br>window.addEventListener("DOMContentLoaded", function() { <br>// <br>init(); <br>},false) ; <br></script>



Zoom and upload images through Canvas and File API

Drag a photo from the folder into the box below, the canvas and JavaScript will automatically scale.



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




Drag the image file here...





Thumbnail:

< ;/div>

< ;canvas id="myCanvas">




< ;/html>

Server page, receive.jsp

Copy code
code As follows:

<%@ page 언어="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/";
파일 photoPathFile = 새 파일(photoPath);
// 참조: http://blog.csdn.net/remote_roamer/article/details/2979822
private boolean saveImageToDisk(byte[] data,String imageName) throws IOException{
int len ​​= data. 길이;
//
// 写入到文件
FileOutputStream outputStream = new FileOutputStream(new File(photoPathFile,imageName));
outputStream.write(데이터);
outputStream.flush();
outputStream.close();
//
true를 반환합니다.
}
private byte[] decode(String imageData)에서 IOException이 발생함{
BASE64Decoder decoder = new BASE64Decoder();
byte[] 데이터 = decoder.decodeBuffer(imageData);
for(int i=0;i{
if(data[i]<0)
{
//调整异常数据
데이터[i] =256;
}
}
//
데이터 반환;
}
%>
<%
문자열 경로 = request.getContextPath();
String basePath = request.getScheme() "://" request.getServerName() ":" request.getServerPort() 경로 "/";
%>
<%
//如果是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 성공 = 0;
문자열 메시지 = "";
if(null == imageData || imageData.length() < 100){
// 数据太短,明显不합리
message = "上传失败,数据太短或不存재";
} else {
// 去除开头不합리적数据
imageData = imageData.substring(30);
imageData = URLDecoder.decode(imageData,"UTF-8");
//System.out.println(imageData);
바이트[] 데이터 = 디코드(imageData);
int len ​​= 데이터.길이;
int len2 = imageData.length();
if(null == imageName || imageName.length() < 1){
imageName = System.currentTimeMillis() ".png";
}
saveImageToDisk(data,imageName);
//
성공 = 1;
message = "上传成功,参数长degree:" len2 "字符,解析文件大小:" len "字节";
}
// 后台打印
System.out.println("message=" message);
%>
{
"메시지": "<%=메시지 %>",
"성공": <%=성공 %>
}

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn