>  기사  >  웹 프론트엔드  >  Canvas 및 File API_html5 튜토리얼 기술을 통해 이미지를 확대/축소하고 업로드하는 전체 예

Canvas 및 File API_html5 튜토리얼 기술을 통해 이미지를 확대/축소하고 업로드하는 전체 예

WBOY
WBOY원래의
2016-05-16 15:49:071538검색

주소 예: Canvas Resize Demo
원저자: Dr. Tom Trenka
원본 날짜: 2013년 8월 6일
번역 날짜: 2013년 8월 8일

Tom Trenka "나의" 블로그에 기사를 쓰는 것은 나에게 큰 영광입니다. Tom은 Dojo 프레임워크의 최초 기여자 중 한 명이었고 SitePen에서 나의 멘토였습니다. 나는 그의 천재성을 최고 수준에서 목격했으며 그는 항상 미래 지향적인 솔루션으로 많은 어려운 문제를 예견했습니다. 그는 항상 외부에서 생각하고, 틀에 얽매이지 않지만 탄탄한 방식으로 주변 문제를 해결합니다. 이 기사는 완벽한 예입니다.
최근 저는 사용자가 서버에 이미지를 업로드하고 우리 회사가 지원하는 수많은 웹사이트의 클라이언트 측에서 사용할 수 있는 사용자 인터페이스 API를 만드는 것에 대해 많은 요청을 받았습니다. 일반적으로 이것은 매우 쉬운 일입니다. 양식을 만들고, 파일 형식 입력 상자를 추가하고, 사용자가 컴퓨터에서 이미지를 선택하도록 하고, 양식 태그 속성에서 enctype="multipart/form-data" 양식을 설정한 다음 업로드합니다. . 꽤 간단하지 않나요? 사실, 여기에 충분히 간단한 예가 있습니다. 입력하려면 클릭하세요
하지만 이미지를 업로드하기 전에 어떤 방식으로든 사전 처리하고 싶다면 어떻게 해야 할까요? 예를 들어, 먼저 이미지 크기를 압축해야 합니다. 아니면 이미지가 png 또는 jpg와 같은 특정 유형의 형식으로만 필요하면 어떻게 해야 합니까?
캔버스를 사용하여 해결하세요!

캔버스 소개
캔버스는 사용자가 일반적으로 JavaScript를 사용하여 페이지에 직접 그래픽을 그릴 수 있도록 하는 HTML5의 새로운 DOM 요소입니다. 다양한 형식 표준도 다릅니다. 예를 들어 SVG는 래스터 API(래스터 API)인 반면 VML은 그리기에는 Adobe Illustrator(벡터)를 사용하고 차이는 Adobe Photoshop(래스터)을 사용하는 것을 고려할 수 있습니다.

캔버스에서 할 수 있는 작업은 이미지를 읽고 렌더링하는 것이며 JavaScript를 통해 이미지 데이터를 조작할 수 있는 것입니다. 주로 다양한 이미지 필터링 기술에 초점을 맞춰 기본적인 이미지 처리를 보여주는 기존 기사가 많이 있지만 우리에게 필요한 것은 이미지 크기를 조정하고 특정 파일 형식으로 변환하는 것뿐입니다. Canvas는 이러한 작업을 완벽하게 수행할 수 있습니다.

원본 이미지의 높이에 관계없이 이미지 높이가 100픽셀을 초과하지 않는 등 우리가 가정한 요구 사항입니다. 기본 코드는 다음과 같습니다.

코드 복사
코드는 다음과 같습니다.

// 매개변수, 최대 높이
var MAX_HEIGHT = 100;
// 렌더링
function render(src){
// 이미지 객체 생성
var image = new Image() ;
// 로드 이벤트 핸들러를 바인딩하고 로드가 완료된 후 실행
image.onload = function(){
// 캔버스 DOM 객체 가져오기
var canvas = document.getElementById("myCanvas ");
// 높이가 기준을 초과하는 경우
if(image.height > MAX_HEIGHT) {
// 너비 비례 스케일링 *=
image.width *= MAX_HEIGHT / image.height ;
image.height = MAX_HEIGHT;
}
// 캔버스의 2D 환경 객체를 가져옵니다.
// 컨텍스트가 관리자이고 캔버스가 집이라는 것을 알 수 있습니다
var ctx = canvas.getContext("2d");//캔버스 화면 지우기
ctx.clearRect(0, 0, canvas.width, canvas.height)//캔버스 너비 및 높이 재설정
canvas.width = image.width;
canvas.height = image.height;
// 캔버스에 이미지를 그립니다.
ctx.drawImage(image, 0, 0, image.width, image .height);
// !!! 이미지는 DOM에 추가되지 않습니다
}
// src 속성을 설정하면 브라우저가 자동으로 로드합니다.
// src 속성을 설정하기 전에 먼저 이벤트를 바인딩해야 한다는 점을 기억하세요. 그렇지 않으면 동기화 문제가 발생합니다.
이미지.src =
}


위 예에서는 캔버스의 toDataURL() 메서드를 사용하여 Base64로 인코딩된 이미지 값을 얻을 수 있습니다(이는 16진수 문자열 또는 이진 데이터 스트림으로 유사하게 이해될 수 있음).
참고: 캔버스의 toDataURL () 획득한 URL은 문자열로 시작하고 클라이언트나 서버에서 필터링해야 하는 22개의 쓸모 없는 데이터 "data:image/png;base64"를 포함합니다.
원칙적으로 브라우저가 지원하는 한 URL 주소 길이에는 제한이 없으며 1024라는 길이 제한은 이전 세대 IE에만 ​​적용됩니다.

실례합니다. 필요한 이미지를 어떻게 구하나요?
착한 소년님, 물어봐주셔서 기뻐요. 파일 입력 상자를 통해 직접 처리할 수는 없습니다. 이 파일 입력 상자 요소에서 얻을 수 있는 것은 사용자가 선택한 파일의 경로뿐입니다. 기존의 상상에 따르면 이 경로 경로 정보를 통해 이미지를 로드할 수 있지만 브라우저에서는 이는 비현실적입니다. (번역자 참고 사항: 브라우저 제조업체는 시장 점유율을 확보하고 최소한 미디어 공격을 피하기 위해 브라우저가 절대적으로 안전한지 확인해야 합니다. 이것이 허용되는 경우 악성 URL은 파일 경로를 연결하여 민감한 특정 정보를 얻으려고 시도할 수 있습니다.) >이 요구 사항을 충족하기 위해 HTML5의 파일 API를 사용하여 사용자 디스크의 파일을 읽고 이 파일을 이미지 소스(src, 소스)로 사용할 수 있습니다.


파일 API 소개 새로운 파일 API 인터페이스는 보안 샌드박스 규칙을 위반하지 않고 사용자 파일 디렉터리를 읽고 나열하는 방법입니다. 샌드박스 제한을 통해 악성 웹사이트는 물론 사용자 디스크에 바이러스를 작성할 수 없습니다.
우리가 사용하려는 파일 읽기 개체는 FileReader입니다. FileReader를 사용하면 개발자가 파일 내용을 읽을 수 있습니다(특정 브라우저의 구현은 매우 다를 수 있음).

이미지 파일의 경로를 얻었다고 가정하고 이전 코드를 사용하면 FileReader를 사용하여 이미지를 로드하고 렌더링하는 것이 쉬워집니다.


코드 복사코드는 다음과 같습니다.
// 이미지 파일 로드(url 경로)
function loadImage(src) {
/ / 이미지 유형이 아닌 파일 필터링
if(!src.type.match(/image.*/)){
if(window.console){
console.log( "선택한 파일 형식 사진이 아님: ", src.type);
} else {
window.confirm("사진 파일만 선택할 수 있습니다.")
}
return; }
// FileReader 객체를 생성하고 렌더링 함수를 호출하여 렌더링을 완료합니다.
var reader = new FileReader()
// 로드 이벤트 자동 콜백 함수 바인딩
reader.onload = function (e){
/ / 이전 렌더링 함수 호출
render(e.target.result)
}
// 파일 내용 읽기
reader.readAsDataURL(src);
};


죄송하지만 파일을 어떻게 구하나요?
작은 흰 토끼야, 인내심을 가져라! 다음 단계는 파일을 얻는 것입니다. 물론 이를 수행하는 방법은 다양합니다. 예를 들어 텍스트 상자를 사용하여 사용자가 파일 경로를 입력할 수 있지만 대부분의 사용자는 개발자가 아니며 어떤 값을 입력해야 할지 모릅니다.
사용자 편의를 위해 Drag and Drop API 인터페이스를 사용합니다. .


드래그 앤 드롭 API 사용
드래그 앤 드롭 인터페이스(드래그 앤 드롭)는 매우 간단합니다. 대부분의 DOM 요소에서 이벤트 핸들러를 구현에 바인딩할 수 있습니다. 사용자가 디스크에서 dom 객체로 파일을 드래그하고 마우스를 놓으면 파일을 읽을 수 있습니다. 코드는 다음과 같습니다.


코드 복사코드는 다음과 같습니다.
function init(){
// DOM 요소 객체 가져오기
var target = document.getElementById("drop-target")
// 드래그오버 방지(DOM 요소 위로 드래그) 이벤트 전달
target.addEventListener("dragover ", function(e){e.preventDefault();}, true);
// 마우스 이벤트를 드래그하여 놓습니다
target.addEventListener("drop", function(e ){
// 기본 이벤트 및 이벤트 전파 방지
e.preventDefault()
// 이전 이미지 로드 함수를 호출합니다. 매개변수는 dataTransfer 객체의 첫 번째 파일입니다.
loadImage(e .dataTransfer.files[ 0]);
},
var setheight = document.getElementById("setheight");
var maxheight = document.getElementById("maxheight"); setheight.addEventListener(" 클릭", 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 게시 방식을 통해 이미지 데이터를 업로드하겠습니다. 다음 예에서는 Dojo 프레임워크를 사용하여 요청을 완료합니다. 물론 다른 Ajax 기술을 사용하여 이를 구현할 수도 있습니다.
Dojo 코드는 다음과 같습니다.

코드 복사
코드는 다음과 같습니다.

// 번역자가 Dojo를 이해하지 못하므로 나중에 jQuery 구현을 첨부하겠습니다
/ / DTK 1.7은 AMD입니다!
require(["dojo/request"], function(request){
// 요청 URL, 매개변수 및 콜백을 설정합니다.
request.post("image -handler.php", {
데이터: {
imageName: "myImage.png",
imageData: encodeURIComponent(document.getElementById("canvas").toDataURL("image/png"))
}
} ).then(function(text){
console.log("서버가 반환됨: ", text);
})

jQuery는 다음과 같이 구현됩니다.


코드 복사코드는 다음과 같습니다.
// 이미지 업로드, jQuery 버전
function sendImage(){
// 캔버스 DOM 개체 가져오기
var canvas = document.getElementById("myCanvas")// 가져오기 Base64로 인코딩된 이미지 데이터, 형식은 문자열
// "data:image/png;base64," 시작 부분에서 클라이언트 또는 서버 측에서 제거해야 하며 다음 부분을 작성할 수 있습니다. 파일에 직접.
var dataurl = canvas.toDataURL("image/png");
// 보안을 위한 URI 인코딩
// data:image/png;base64, 시작
var imagedata = encodeURIComponent( dataurl) ;
//var url = $("#form").attr("action");
// 1. 양식 처리가 어려운 경우 숨겨진 숨겨진 필드를 사용하여 요청을 설정할 수 있습니다. 주소
//
var url = $("input[name='action']").val ();
// 2. DOM 객체의 속성을 직접 사용하여
//
// var url = $("#imageaction").attr("action");
// 문자열이므로 서버에서 데이터 트랜스코딩, 파일 쓰기 작업 등을 수행해야 합니다.
// 개인 합의, 모든 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)
}


자, 끝났습니다! 여러분이 해야 할 일은 이미지의 크기를 제어할 수 있는 간단한 사용자 인터페이스를 만드는 것뿐입니다. 서버에 업로드된 데이터는 다중 부분/양식 데이터의 enctype을 처리할 필요가 없습니다. 간단한 POST 양식 핸들러만으로 충분합니다.
다음은 전체 코드 예입니다.




코드 복사
코드는 다음과 같습니다.

<%@ page 언어="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
문자열 경로 = request.getContextPath();
String basePath = request.getScheme() "://" request.getServerName() ":" request.getServerPort() 경로 "/";
%>


<머리>
<제목>통로Canvas及File API缩放并上传图文






<스크립트>
// 参数, 最大높이
var MAX_HEIGHT = 100;
// 渲染
function render(src){
// 创建一个 Image 对象
var image = new Image(); // 如果고도 높이
if(image.height > MAX_HEIGHT) {
// 宽島等比例缩放 *=
image.width *= MAX_HEIGHT / image.height;
이미지.높이 = MAX_HEIGHT;
}
// 获取 캔버스의 2d 环境对象,
// 可以理解Context是管理员,canvas是房子
var ctx = canvas.getContext("2d");
// canvas清屏
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 캔버스 크기 높이
canvas.width = image.width;
canvas.height = 이미지.높이;
// 将图image绘제到canvas上
ctx.drawImage(image, 0, 0, image.width, image.height);
//!!! 注意,image 没有加入到 dom 之中
};
// 设置src属性,浏览器会自动加载。
// 记住必须先绑定事件,才能设置src属性,否则会出同步问题。
image.src = src;
};
// 加载 图image文件(url路径)
function loadImage(src){
// 过滤掉 비 image 类型的文件
if(!src.type.match(/image.*/ )){
if(window.console){
console.log("选择的文件类型不是图picture: ", src.type);
} else {
window.confirm("只能选择图文件");
}
반환;
}
// 创建 FileReader 对象 并调사용 render 函数来完成渲染.
var reader = new FileReader(); };
// 读取文件内容
reader.readAsDataURL(src);
}; // 获取Base64编码后的图image数据,格式是字符串
// "data:image/png;base64,"开头,需要在客户端或者服务器端将其去掉,后면적부분可以直接写入文件。
var dataurl = canvas.toDataURL("image/png");
// 为안전 对URI进行编码
// data:image/png;base64, 开头
var imagedata = encodeURIComponent(dataurl);
//var url = $("#form").attr("action");
// 1. 如果form表单不好处理,可以使用某个hidden隐藏域来设置请求地址
//
var url = $("input[name='action']").val();
// 2. 也可以直接用某个dom对象的属性来获取
//
// var url = $("#imageaction").attr("action");
// 因为是string,所以服务器需要对数据进行转码,写文件操作等。
// 个人约定,所有http参数name字전체부소写
console.log (데이터URL);
//console.log(이미지데이터);
var data = {
imagename: "myImage.png",
imagedata: imagedata
};
jQuery.ajax( {
url : url,
data : data,
type : "POST",
// 期待的返回值类型
dataType: "json",
완료: 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 ")"); Tip2.text('解析错误!');
return false
} else {
$tip2.text(json.message)
//console.dir(json );
//console.log(xhr.responseText)
}
});
};
함수 초기화(){
// 获取DOM元素对象
var target = document.getElementById("drop-target");
// 드래그오버 방지(DOM 요소 위로 드래그) 이벤트 전달
target.addEventListener("dragover", function(e){e.preventDefault( ) ;}, true);
// 마우스 이벤트 끌어 놓기
target.addEventListener("drop", function(e){
// 기본 이벤트 및 이벤트 전파 방지
e.preventDefault ();
// 이전 이미지 로드 함수를 호출합니다. 매개변수는 dataTransfer 개체
loadImage(e.dataTransfer.files[0])
},
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) ; >


캔버스 및 파일 API를 통해 이미지 업로드

폴더에서 아래 상자로 사진을 드래그하면 캔버스와 JavaScript가 자동으로 크기가 조정됩니다.



< maxheight" value="100"/>




이미지 파일을 여기로 드래그하세요...


썸네일:
< ;canvas id="myCanvas">< ;/캔버스>





서버 페이지, receive.jsp





코드 복사



코드는 다음과 같습니다.

<%@ 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);
%>
{
"메시지": "<%=메시지 %>",
"성공": <%=성공 %>
}
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.