Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
538 views
in Technique[技术] by (71.8m points)

javascript - Canvas.toDataURL()被污染的画布可能无法导出(Canvas.toDataURL() Tainted canvases may not be exported)

I am trying to use javascript, html, css to create a page that I can resize an image from an online link.(我正在尝试使用javascript,html,css创建一个页面,我可以通过在线链接调整图像的大小。)

However, when resized, I faced the error that Tainted canvases may not be exported while using Canvas.toDataURL() .(但是,在调整大小时,我遇到以下错误:使用Canvas.toDataURL()时,可能无法导出污染的画布。) I have searched the issue in google and here.(我已经在Google和此处搜索了此问题。) Somebody suggested to amend the photo's crossorigin to anonymous or '*'.(有人建议将照片的跨域修改为匿名或“ *”。) I tried both methods but it doesn't work for me.(我尝试了两种方法,但对我不起作用。) I wonder anyone can offer help.(我想知道有人能提供帮助吗?) My code is in the below link.(我的代码在下面的链接中。) https://jsfiddle.net/pangkachun/7axkq9pe/1/(https://jsfiddle.net/pangkachun/7axkq9pe/1/) var min_img_width = 60; var min_img_height = 60; var max_img_width = 1000; var max_img_height = 1000; var resizeableImage = function(image_target) { // Some variable and settings var $container, orig_src = new Image(), image_target = $(image_target).get(0), event_state = {}, constrain = false, min_width = min_img_width, // Change as required min_height = min_img_height, max_width = max_img_width, // Change as required max_height = max_img_height, resize_canvas = document.createElement('canvas'), // ----------------- function to int the page ----------------------// init = function(){ // When resizing, we will always use this copy of the original as the base orig_src.src = image_target.src; orig_src.crossorigin = 'anonymous'; // Wrap the image with the container and add resize handles $(image_target).wrap('<div class="resize-container"></div>') .before('<span class="resize-handle resize-handle-nw"></span>') .before('<span class="resize-handle resize-handle-ne"></span>') .after('<span class="resize-handle resize-handle-se"></span>') .after('<span class="resize-handle resize-handle-sw"></span>'); // Assign the container to a variable $container = $(image_target).parent('.resize-container'); // Add events (one for resize (resize handle) and one for moving - img) // addEventListenor -> mouse touchdown, resize handle, resize_img $container.on('mousedown touchstart', '.resize-handle', startResize); }; // ------------------ end function to int the page -------------------------// // to save the data upon a event is fired saveEventState = function(e){ // Save the initial event details and container state event_state.container_width = $container.width(); event_state.container_height = $container.height(); event_state.container_left = $container.offset().left; event_state.container_top = $container.offset().top; event_state.mouse_x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft(); event_state.mouse_y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop(); // This is a fix for mobile safari // For some reason it does not allow a direct copy of the touches property if(typeof e.originalEvent.touches !== 'undefined'){ event_state.touches = []; $.each(e.originalEvent.touches, function(i, ob){ event_state.touches[i] = {}; event_state.touches[i].clientX = 0+ob.clientX; event_state.touches[i].clientY = 0+ob.clientY; }); } event_state.evnt = e; }; // function to redraw the image based on width and height redrawImage = function(width, height){ resize_canvas.width = width; resize_canvas.height = height; resize_canvas.getContext('2d').drawImage(orig_src, 0, 0, width, height); $(image_target).attr('src', resize_canvas.toDataURL("image/png")); }; //------------------------ resizing function starts ----------------------------// startResize = function(e){ e.preventDefault(); e.stopPropagation(); saveEventState(e); $(document).on('mousemove touchmove', resizing); $(document).on('mouseup touchend', endResize); }; endResize = function(e){ e.preventDefault(); $(document).off('mouseup touchend', endResize); $(document).off('mousemove touchmove', resizing); }; resizing = function(e){ var mouse = {}, width, height, left, top, offset=$container.offset(); mouse.x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + $(window).scrollLeft(); mouse.y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + $(window).scrollTop(); // Position image differently depending on the corner dragged and constraints if( $(event_state.evnt.target).hasClass('resize-handle-se') ){ width = mouse.x - event_state.container_left; height = mouse.y - event_state.container_top; left = event_state.container_left; top = event_state.container_top; } else if($(event_state.evnt.target).hasClass('resize-handle-sw') ){ width = event_state.container_width - (mouse.x - event_state.container_left); height = mouse.y - event_state.container_top; left = mouse.x; top = event_state.container_top; } else if($(event_state.evnt.target).hasClass('resize-handle-nw') ){ width = event_state.container_width - (mouse.x - event_state.container_left); height = event_state.container_height - (mouse.y - event_state.container_top); left = mouse.x; top = mouse.y; if(constrain || e.shiftKey){ top = mouse.y - ((width / orig_src.width * orig_src.height) - height); } } else if($(event_state.evnt.target).hasClass('resize-handle-ne') ){ width = mouse.x - event_state.container_left; height = event_state.container_height - (mouse.y - event_state.container_top); left = event_state.container_left; top = mouse.y; } if(width > min_width && height > min_height && width < max_width && height < max_height){ // To improve performance you might limit how often resizeImage() is called redrawImage(width, height); // Without this Firefox will not re-calculate the the image dimensions until drag end $container.offset({'left': left, 'top': top}); } } //------------------------ resizing functino end ----------------------------// init(); }; resizeableImage($('.resize-image')); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!DOCTYPE html> <html lang="en" class="no-js"> <head> <title>Image Resizing with Canvas</title> <link rel="stylesheet" type="text/css" href="css/component.css" /> <!--[if IE]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> <body> <div class="container"> <div class="content"> <header class="codrops-header"> <h1>Image Resizing &amp; Cropping <br /><span>with Canvas</span></h1> </header> <div class="component"> <div class="overlay"> <div class="overlay-inner"> </div> </div> <img class="resize-image" id='test-img'crossorigin="anonymous" src="https://static-cdn.pixlr.com/images/image-design.png" alt="image for resizing"> </div> </div><!-- /content --> </div> <!-- /container --> <script src="js/jquery-2.1.1.min.js"></script> <script src="js/component.js"></script> </body> </html> Thanks a lot.(非常感谢。)   ask by Elvin Pang translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are a couple ways to get around this, but all of them will require at least temporarily hosting the image on your server.(有几种解决方法,但是所有这些方法都至少需要在服务器上临时托管映像。)

The simplest option would be to write a simple cgi script that takes an url as a parameter, fetches the image at that url, and sends it on to the browser as though it was on your server.(最简单的选择是编写一个简单的cgi脚本,该脚本将url作为参数,获取该url处的图像,然后将其发送到浏览器,就像它在服务器上一样。) You could also use a file upload form if you want the user to be able to select a local image.(如果希望用户能够选择本地图像,也可以使用文件上传表单。) Note that if you do this, you would want to be aware of the security implications of grabbing user-selected files and serving them as if they were on your own server.(请注意,如果执行此操作,则需要了解捕获用户选择的文件并将其提供给用户的文件就像在您自己的服务器上一样对安全性的影响。) You would, at a minimum, want to make sure the files were valid images, and not, say, javascript files (which might lead to code injection attacks).(您至少要确保文件是有效图像,而不是javascript文件(这可能导致代码注入攻击)。) The reason exporting of tainted canvas data is disallowed is that it's a user security issue.(禁止导出受污染的画布数据的原因是这是用户安全问题。) Remote sites can send different images to different users, and if your site can gain access to that just by drawing it on a canvas, that method could be used to steal a user's private data.(远程站点可以将不同的图像发送给不同的用户,如果您的站点仅通过在画布上绘制就可以访问该图像,则可以使用该方法来窃取用户的私人数据。) For example, Amazon used to let website owners embed an image in their site that would end up being a customized ad including a greeting and the end-user's name.(例如,亚马逊过去曾让网站所有者在他们的网站中嵌入图片,而该图片最终将成为包含问候语和最终用户名称的定制广告。) If you could paint that on a canvas and export the data, you could send that data back to your webserver and OCR it to learn the name of the end-user.(如果可以将其绘制在画布上并导出数据,则可以将该数据发送回Web服务器并对其进行OCR,以了解最终用户的名称。)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...