Canvas bị nhiễm độc có thể không được xuất khẩu


185

Tôi muốn lưu canvas của tôi vào một img. Tôi có chức năng này:

function save() {
    document.getElementById("canvasimg").style.border = "2px solid";
    var dataURL = canvas.toDataURL();
    document.getElementById("canvasimg").src = dataURL;
    document.getElementById("canvasimg").style.display = "inline";
}

Nó cho tôi lỗi:

Uncaught SecurityError: Không thể thực thi 'toDataURL' trên 'HTMLCanvasEuity': Canvas canvas bị nhiễm độc có thể không được xuất.

Tôi nên làm gì?


Trong trình duyệt nào? stackoverflow.com/a/21362569/476716 tuyên bố đây là một lỗi.
OrangeDog

1
trên chrome và trên firefox
user3465096

Câu trả lời:


177

Vì lý do bảo mật, ổ đĩa cục bộ của bạn được khai báo là "tên miền khác" và sẽ làm mờ khung vẽ.

(Đó là vì thông tin nhạy cảm nhất của bạn có khả năng trên ổ đĩa cục bộ của bạn!).

Trong khi thử nghiệm, hãy thử các cách giải quyết này:

  • Đặt tất cả các tệp liên quan đến trang (.html, .jpg, .js, .css, v.v.) trên máy tính để bàn của bạn (không phải trong các thư mục phụ).

  • Đăng hình ảnh của bạn lên một trang web hỗ trợ chia sẻ tên miền chéo (như dropbox.com). Hãy chắc chắn rằng bạn đã đặt hình ảnh của mình vào thư mục chung của dropbox và cũng đặt cờ gốc chéo khi tải xuống hình ảnh (var img = new Image (); img.crossOrigin = "nặc danh" ...)

  • Cài đặt máy chủ web trên máy tính phát triển của bạn (cả máy chủ web IIS và PHP đều có phiên bản miễn phí hoạt động độc đáo trên máy tính cục bộ).


15
Cảm ơn, thiết lập thuộc tính img.crossOrigin đã giúp tôi!
zumek

5
@markE - Tôi đã tải dữ liệu hình ảnh từ localStorage thay vì tải từ tệp hoặc bất kỳ url nào, sau đó thực hiện một số thao tác với nó như thêm văn bản. Sau đó cố gắng tìm lại nó cho localStorage bằng cách sử dụng toDataURL (). Nhưng nó cho thấy "Không thể thực thi 'toDataURL' trên 'HTMLCanvasEuity': Canvas canvas bị nhiễm độc có thể không được xuất". Trong trường hợp này, tôi không sử dụng bất kỳ tệp exteranl hoặc url nào để gặp sự cố tên miền chéo. Vậy thì tại sao nó lại dẫn đến lỗi này?
Sajith

2
@Saijth - Bạn có thể muốn xác minh đường dẫn được sử dụng cho hình ảnh. Tôi cũng gặp vấn đề này vì tôi đang kiểm tra trực tiếp máy chủ ảo cục bộ của mình thông qua IP của nó (127.0.xx /) nhưng một số hình ảnh được liên kết thông qua tên miền (localhost /). Khi tôi sử dụng localhost thay vì nó hoạt động. Vì vậy, hãy chắc chắn rằng bạn không chạy vào một cái gì đó như thế.
Victor D.

1
(1) Xem nó từ máy chủ web xampp, localhost / tệp thay vì c: / localdisk / file; sau đó chrome sẽ không phàn nàn về Lỗi bảo mật. (2) Hoặc sử dụng cờ này khi bắt đầu chrome: --allow-file-access-from-files
mosh

1
Chỉ cần thêm một vấn đề có thể khác: nếu bạn đang cố xuất một khung vẽ có chứa một Svg với ForeignObject, một số trình duyệt sẽ đánh dấu nó là bị hỏng.
HairyFotr

128

Trong thẻ img, đặt crossorigin thành Ẩn danh.

<img crossorigin="anonymous"></img>

60
Nhưng phải làm gì trong trường hợp canvas html5, không phải các phần tử img
Graphics123

11
Trong trường hợp của một phần tử canvas, nguồn gốc của vấn đề luôn là với một số hình ảnh (hoặc hình ảnh) mà bạn đang vẽ lên nó. Vì vậy, bạn chỉ cần theo dõi hình ảnh và đặt thuộc tính crossOrigin của nó như được chỉ định, trước khi tải nó.
Fernando Echeverria

3
Điều này đã cứu ngày của tôi!
Chang

1
Rất vui được giúp đỡ :)
Annia Martinez

9
12 giờ sáng tôi đang ở trong văn phòng và tôi tìm thấy câu trả lời đơn giản này, đây là niềm hạnh phúc thuần túy
Dheeraj

26

Nếu ai đó xem câu trả lời của tôi, bạn có thể trong tình trạng này:

1. Cố gắng lấy ảnh chụp màn hình bản đồ trong canvas bằng openlayers (phiên bản> = 3)
2. Và xem ví dụ về xuất bản đồ
3. Sử dụng ol.source.XYZ để hiển thị lớp bản đồ

Chơi lô tô!

Sử dụng ol.source.XYZ.crossOrigin = 'Ẩn danh' để giải quyết sự nhầm lẫn của bạn. Hoặc thích mã sau đây:

     var baseLayer = new ol.layer.Tile({
         name: 'basic',
         source: new ol.source.XYZ({
             url: options.baseMap.basic,
             crossOrigin: "Anonymous"
         })
     });

1
tuyệt diệu. Hữu ích cho tất cả các nguồn, như TileImage và như vậy.
Phil

Béo! Chính xác những gì tôi đang tìm kiếm cho mình, dễ dàng sửa chữa cho bản demo OpenLayers tôi đang làm.
Marc

Tôi đang sử dụng các lớp gạch vector và sau khi thêm quyền này vào nguồn nhưng nó cũng không hoạt động!
mahdi n75

Chính xác những gì tôi cần :)
Ray

16

Nếu bạn đang sử dụng ctx.drawImage()chức năng, bạn có thể làm như sau:

var img = loadImage('../yourimage.png', callback);

function loadImage(src, callback) {
    var img = new Image();

    img.onload = callback;
    img.setAttribute('crossorigin', 'anonymous'); // works for me

    img.src = src;

    return img;
}

Và trong cuộc gọi lại của bạn, bây giờ bạn có thể sử dụng ctx.drawImagevà xuất nó bằng cách sử dụngtoDataURL


6
Điều này đã không làm việc cho tôi. Vẫn nhận được thông Tainted canvases may not be exported.báo lỗi.
Sam Sverko

1
nó làm việc cho tôi cảm ơn. @SamSverko đảm bảo đặt thuộc tính trước img.src.
aijogja

14

Trong trường hợp của tôi, tôi đã vẽ lên một thẻ vải từ video. Để giải quyết lỗi canvas bị nhiễm bẩn, tôi phải làm hai việc:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Đảm bảo tiêu đề Kiểm soát truy cập-Cho phép-Xuất xứ được đặt trong phản hồi nguồn video (thiết lập đúng của crossdomain.example.com)
  • Đặt thẻ video thành crossorigin = "nặc danh"

5

Có vẻ như bạn đang sử dụng một hình ảnh từ một URL chưa đặt tiêu đề Access-Control-Allow-Origin chính xác và do đó xảy ra sự cố .. Bạn có thể tìm nạp hình ảnh đó từ máy chủ của mình và lấy nó từ máy chủ của mình để tránh các sự cố CORS ..


Bạn có thể chính xác hơn về câu trả lời của bạn, bởi vì tôi không thực sự biết tất cả các khái niệm đó. Làm thế nào để tôi lấy hình ảnh đó từ máy chủ của tôi?
dùng3465096

bạn lấy hình ảnh đó từ đâu, nó từ máy chủ của bạn hay một cái khác?
Prasanna Aarthi

Nó diễn ra như sau: loadImage ("example.jpg", 0, 0, 500, 300); Tôi có thể đặt url hình ảnh ngẫu nhiên hoặc hình ảnh trên cùng một thư mục trong máy tính của mình, nó vẫn giống nhau
user3465096

vâng, nhưng tôi chỉ tạo ra hình ảnh trên sơn và nó vẫn giống nhau
user3465096

1
Tôi đã cho Access-Control-Allow-Origin: * cho tệp, nhưng nó vẫn hiển thị lỗi
Harikrishnan

4

Tôi đã giải quyết vấn đề bằng cách sử dụng useCORS: truetùy chọn

 html2canvas(document.getElementsByClassName("droppable-area")[0], { useCORS:true}).then(function (canvas){
        var imgBase64 = canvas.toDataURL();
        // console.log("imgBase64:", imgBase64);
        var imgURL = "data:image/" + imgBase64;
        var triggerDownload = $("<a>").attr("href", imgURL).attr("download", "layout_"+new Date().getTime()+".jpeg").appendTo("body");
        triggerDownload[0].click();
        triggerDownload.remove();
    });

3

Kiểm tra [hình ảnh được bật CORS] [1] từ MDN. Về cơ bản, bạn phải có một máy chủ lưu trữ hình ảnh với tiêu đề Access-Control-Allow-Origin thích hợp.

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

Bạn sẽ có thể lưu những hình ảnh đó vào DOM Storage như thể chúng được phục vụ từ miền của bạn nếu không bạn sẽ gặp phải vấn đề bảo mật.

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; // insert image url here

img.crossOrigin = "Anonymous";

img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage( img, 0, 0 );
    localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
}


Mặc dù liên kết này có thể trả lời câu hỏi, tốt hơn là bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi. - Từ đánh giá
Gowtham Shiva

Cảm ơn đã thông báo. Tôi chỉ cần thêm nội dung từ liên kết MDN :)
BerlinaLi

1

Cũng giống như bản dựng trên @ markE's answer nếu bạn muốn tạo một máy chủ cục bộ. Bạn sẽ không gặp lỗi này trên máy chủ cục bộ.

Nếu bạn đã cài đặt PHP trên máy tính của mình:

  1. Mở terminal / cmd của bạn
  2. Điều hướng vào thư mục chứa các tập tin trang web của bạn
  3. Trong khi trong thư mục này, hãy chạy lệnh php -S localhost:3000← Lưu ý viết hoa 'S'
  4. Mở trình duyệt của bạn và trong thanh URL, truy cập localhost: 3000 . Trang web của bạn nên được chạy ở đó.

hoặc là

Nếu bạn đã cài đặt Node.js trên máy tính của mình:

  1. Mở terminal / cmd của bạn
  2. Điều hướng vào thư mục chứa các tập tin trang web của bạn
  3. Trong khi trong thư mục này, chạy lệnh npm init -y
  4. Chạy npm install live-server -ghoặc sudo npm install live-server -gtrên máy mac
  5. Chạy live-servervà nó sẽ tự động mở ra một tab mới trong trình duyệt khi trang web của bạn mở.

Lưu ý: hãy nhớ có tệp index.html trong thư mục gốc của thư mục của bạn nếu không bạn có thể gặp một số vấn đề.


0

Tôi cũng đã giải quyết lỗi này bằng cách thêm useCORS : true,vào mã của mình như -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.