ผืนผ้าใบที่เสียอาจไม่สามารถส่งออกได้


187

ฉันต้องการบันทึกผืนผ้าใบของฉันไว้ที่ img ฉันมีฟังก์ชั่นนี้:

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

มันทำให้ฉันมีข้อผิดพลาด:

ไม่ได้เข้ารหัส SecurityError: ล้มเหลวในการเรียกใช้งาน 'toDataURL' บน 'HTMLCanvasElement': ผืนผ้าใบที่เสียอาจไม่สามารถส่งออกได้

ฉันควรทำอย่างไรดี?


เบราว์เซอร์ใด stackoverflow.com/a/21362569/476716อ้างว่านี่เป็นข้อผิดพลาด
OrangeDog

1
บน chrome และบน firefox
user3465096

คำตอบ:


180

เพื่อเหตุผลด้านความปลอดภัยไดรฟ์ในระบบของคุณได้รับการประกาศว่าเป็น "โดเมนอื่น" และจะทำให้พื้นที่ขาดหาย

(นั่นเป็นเพราะข้อมูลที่ละเอียดอ่อนที่สุดของคุณน่าจะอยู่ในไดรฟ์ในเครื่องของคุณ!)

ขณะทดสอบให้ลองวิธีแก้ปัญหาต่อไปนี้:

  • วางไฟล์ที่เกี่ยวข้องกับหน้าทั้งหมด (.html, .jpg, .js, .css ฯลฯ ) บนเดสก์ท็อปของคุณ (ไม่ใช่ในโฟลเดอร์ย่อย)

  • โพสต์ภาพของคุณไปยังเว็บไซต์ที่รองรับการแชร์ข้ามโดเมน (เช่น dropbox.com) ต้องแน่ใจว่าคุณใส่รูปภาพของคุณในโฟลเดอร์สาธารณะของดรอปบ็อกซ์และตั้งค่าธงไขว้กำเนิดเมื่อดาวน์โหลดรูปภาพ (var img = new Image (); img.crossOrigin = "ไม่ระบุชื่อ" ... )

  • ติดตั้งเว็บเซิร์ฟเวอร์บนคอมพิวเตอร์พัฒนาของคุณ (IIS และ PHP เว็บเซิร์ฟเวอร์ทั้งสองรุ่นมีรุ่นฟรีที่ใช้งานได้ดีบนคอมพิวเตอร์ท้องถิ่น)


16
ขอบคุณการตั้งค่าคุณสมบัติ img.crossOrigin ช่วยฉัน!
zumek

5
@markE - ฉันโหลดข้อมูลภาพจาก localStorage แทนการโหลดจากไฟล์หรือ URL ใด ๆ จากนั้นทำการจัดการบางอย่างเช่นเพิ่มข้อความ จากนั้นพยายามที่จะกลับไปที่ localStorage โดยใช้ toDataURL () แต่จะแสดง "ล้มเหลวในการเรียกใช้งาน 'toDataURL' บน 'HTMLCanvasElement': ผืนผ้าใบที่ปนเปื้อนอาจไม่สามารถส่งออกได้" ในกรณีนี้ฉันไม่ได้ใช้ไฟล์ exteranl หรือ URL ใด ๆ เพื่อรับปัญหาข้ามโดเมน ถ้าอย่างนั้นทำไมมันถึงเกิดข้อผิดพลาดนี้?
Sajith

2
@Saijth - คุณอาจต้องการตรวจสอบเส้นทางที่ใช้สำหรับภาพ ฉันมีปัญหานี้เช่นกันเพราะฉันทดสอบโดยตรงว่าเซิร์ฟเวอร์เสมือนในพื้นที่ของฉันผ่าน IP (127.0.xx /) แต่ภาพบางรูปเชื่อมโยงกับโดเมน (localhost /) เมื่อฉันใช้ localhost แทนมันได้ผล ดังนั้นตรวจสอบให้แน่ใจว่าคุณไม่พบสิ่งที่ต้องการ
Victor D.

1
(1) ดูจาก xampp webserver, localhost / file แทน c: / localdisk / file; แล้ว Chrome จะไม่บ่นเกี่ยวกับข้อผิดพลาดด้านความปลอดภัย (2) หรือใช้การตั้งค่าสถานะนี้เมื่อเริ่มการทำงานของ chrome: --allow-file-access-from-files
mosh

1
เพียงเพิ่มปัญหาอื่นที่เป็นไปได้: หากคุณกำลังพยายามส่งออก Canvas ที่มี svg ด้วย ForeignObject เบราว์เซอร์บางตัวจะทำเครื่องหมายว่าไม่บริสุทธิ์
HairyFotr

128

ในแท็ก img ตั้งค่า crossorigin เป็น Anonymous

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

61
แต่สิ่งที่ต้องทำในกรณีของผ้าใบ html5 ไม่ใช่องค์ประกอบของ img
graphics123

11
ในกรณีขององค์ประกอบผ้าใบแหล่งที่มาของปัญหามักจะมีรูปภาพ (หรือภาพ) ที่คุณวาดลงไป ดังนั้นคุณต้องติดตามภาพและตั้งค่าคุณสมบัติ crossOrigin ตามที่ระบุไว้ก่อนที่จะโหลด
Fernando Echeverria

3
สิ่งนี้ช่วยชีวิตฉันไว้!
ช้าง

1
มีความสุขที่ได้ช่วย :)
Annia Martinez

9
มันเป็นเวลา 12.00 น. ในสำนักงานและฉันพบคำตอบง่ายๆนี้นี่คือความสุขที่แท้จริง
Dheeraj

26

หากมีคนดูคำตอบของฉันคุณอาจอยู่ในเงื่อนไขนี้:

1. พยายามรับภาพหน้าจอแผนที่ในแคนวาสโดยใช้ openlayers (เวอร์ชั่น> = 3)
2. และดูตัวอย่างของการส่งออกแผนที่
3. การใช้ ol.source.XYZ เพื่อแสดงเลเยอร์แผนที่

บิงโก!

ใช้ol.source.XYZ.crossOrigin = 'Anonymous'เพื่อแก้ไขความสับสนของคุณ หรือชอบรหัสต่อไปนี้:

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

1
น่าอัศจรรย์ มีประโยชน์สำหรับทุกแหล่งเช่น TileImage และเช่นกัน
ฟิล

Fatastic! สิ่งที่ฉันกำลังมองหาตัวเองแก้ไขการสาธิต OpenLayers ได้อย่างง่ายดาย
Marc

ฉันใช้เลเยอร์แผ่นเวคเตอร์และหลังจากเพิ่มคุณสมบัตินี้ลงในแหล่งที่มาแล้ว แต่ก็ไม่ทำงานเช่นกัน!
mahdi n75

สิ่งที่ฉันต้องการแน่นอน :)
เรย์

17

หากคุณใช้ctx.drawImage()ฟังก์ชั่นคุณสามารถทำสิ่งต่อไปนี้:

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;
}

และในการติดต่อกลับคุณสามารถใช้ctx.drawImageและส่งออกโดยใช้toDataURL


6
สิ่งนี้ไม่ได้ผลสำหรับฉัน ยังคงได้รับTainted canvases may not be exported.ข้อความข้อผิดพลาด
Sam Sverko

1
มันใช้งานได้สำหรับฉัน ขอบคุณ @SamSverko ตรวจสอบให้แน่ใจว่าได้ตั้งค่าแอตทริบิวต์ก่อน img.src
aijogja

14

ในกรณีของฉันฉันวาดลงบนแท็กผ้าใบจากวิดีโอ เพื่อแก้ไขข้อผิดพลาดของผ้าใบที่ปนเปื้อนฉันต้องทำสองสิ่ง:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • ตรวจสอบให้แน่ใจว่าการตั้งค่าการเข้าถึงการควบคุมอนุญาตให้กำเนิดในการตอบสนองแหล่งวิดีโอ (การตั้งค่าที่เหมาะสมของ crossdomain.example.com)
  • ตั้งค่าแท็กวิดีโอให้มี crossorigin = "anonymous"

5

ดูเหมือนว่าคุณกำลังใช้ภาพจาก URL ที่ยังไม่ได้ตั้งค่าส่วนหัว Access-Control-Allow-Origin ที่ถูกต้องและทำให้เกิดปัญหา .. คุณสามารถดึงภาพนั้นจากเซิร์ฟเวอร์ของคุณและรับจากเซิร์ฟเวอร์ของคุณเพื่อหลีกเลี่ยงปัญหา CORS ..


เป็นไปได้ไหมที่คุณจะแม่นยำมากขึ้นเกี่ยวกับคำตอบของคุณเพราะฉันไม่รู้แนวคิดทั้งหมดนั้นจริง ๆ ฉันจะดึงภาพนั้นจากเซิร์ฟเวอร์ของฉันได้อย่างไร
user3465096

คุณดึงภาพนั้นมาจากที่ใดมันมาจากเซิร์ฟเวอร์ของคุณหรือรูปภาพอื่น
Prasanna Aarthi

มันจะเป็นดังนี้: loadImage ("example.jpg", 0, 0, 500, 300); ฉันสามารถใส่ URL แบบสุ่มหรือรูปในโฟลเดอร์เดียวกันในคอมพิวเตอร์ของฉันมันยังคงเหมือนเดิม
user3465096

ใช่ แต่ฉันเพิ่งสร้างภาพบนสีและมันก็ยังคงเหมือนเดิม
user3465096

1
ฉันให้ Access-Control-Allow-Origin: * สำหรับไฟล์ แต่ก็ยังแสดงข้อผิดพลาด
Harikrishnan

5

ฉันแก้ไขปัญหาโดยใช้useCORS: trueตัวเลือก

 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

ลองดู [ภาพที่เปิดใช้งาน CORS] [1] จาก MDN โดยทั่วไปคุณต้องมีเซิร์ฟเวอร์ที่โฮสต์อิมเมจที่มีส่วนหัว Access-Control-Allow-Origin ที่เหมาะสม

<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>

คุณจะสามารถบันทึกภาพเหล่านั้นไปยังที่เก็บข้อมูล DOM ได้ราวกับว่าพวกเขาได้รับบริการจากโดเมนของคุณมิฉะนั้นคุณจะประสบปัญหาด้านความปลอดภัย

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;
}


แม้ว่าลิงก์นี้อาจตอบคำถามได้ดีกว่าหากรวมส่วนสำคัญของคำตอบไว้ที่นี่และให้ลิงก์สำหรับการอ้างอิง คำตอบสำหรับลิงก์เท่านั้นอาจไม่ถูกต้องหากหน้าเว็บที่เชื่อมโยงมีการเปลี่ยนแปลง - จากรีวิว
Gowtham Shiva

ขอบคุณสำหรับการแจ้งเตือน ฉันเพียงแค่เพิ่มเนื้อหาจากการเชื่อมโยง MDN :)
BerlinaLi

1

เช่นเดียวกับการสร้างคำตอบของ @ markE หากคุณต้องการสร้างเซิร์ฟเวอร์ภายใน คุณจะไม่มีข้อผิดพลาดนี้บนเซิร์ฟเวอร์ภายใน

หากคุณติดตั้ง PHP ไว้ในคอมพิวเตอร์ของคุณ:

  1. เปิด terminal / cmd ของคุณ
  2. นำทางไปยังโฟลเดอร์ที่มีไฟล์เว็บไซต์ของคุณอยู่
  3. ในขณะที่อยู่ในโฟลเดอร์นี้ให้เรียกใช้คำสั่งphp -S localhost:3000←สังเกตว่าตัวพิมพ์ใหญ่
  4. เปิดเบราว์เซอร์ของคุณและในแถบ URL ไปที่localhost: 3000 เว็บไซต์ของคุณควรจะทำงานที่นั่น

หรือ

หากคุณติดตั้ง Node.js บนคอมพิวเตอร์ของคุณ:

  1. เปิด terminal / cmd ของคุณ
  2. นำทางไปยังโฟลเดอร์ที่มีไฟล์เว็บไซต์ของคุณอยู่
  3. ในขณะที่อยู่ในโฟลเดอร์นี้ให้เรียกใช้คำสั่ง npm init -y
  4. เรียกใช้npm install live-server -gหรือsudo npm install live-server -gบน mac
  5. เรียกใช้live-serverและควรเปิดแท็บใหม่ในเบราว์เซอร์โดยอัตโนมัติเมื่อเว็บไซต์ของคุณเปิด

หมายเหตุ:อย่าลืมมีไฟล์ index.html ในรูทของโฟลเดอร์ของคุณมิฉะนั้นคุณอาจมีปัญหา


0

ฉันยังแก้ไขข้อผิดพลาดนี้โดยการเพิ่มuseCORS : true,รหัสของฉันเช่น -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.