Html2canvas: فشل تنفيذ "toDataURL" على "HTMLCanvasElement": قد لا يتم تصدير اللوحات الملوثة.

تم إنشاؤها على ٢ أغسطس ٢٠١٨  ·  12تعليقات  ·  مصدر: niklasvh/html2canvas

var canvasPromise  = html2canvas(document.body, {
                allowTaint: true,
                useCORS: true
            });
canvasPromise.then(function(canvas) {
    document.body.appendChild(canvas);
    console.log(canvas);
    canvas.toDataURL('image/png');
});

تقارير الأخطاء:

غير معلوم (في الوعد) DOMException: فشل تنفيذ "toDataURL" على "HTMLCanvasElement": قد لا يتم تصدير اللوحات الملوثة.

  • تم اختبار إصدار html2canvas باستخدام:
  • Chrome 67.0.3396.99
  • نظام التشغيل Windows 10

التعليق الأكثر فائدة

لدي أيضا نفس القضايا.
هل وجدت حلا أو حلا؟

ال 12 كومينتر

لدي أيضا نفس القضايا.
هل وجدت حلا أو حلا؟

أفعل نفس الشيء في Firefox 61.0.2 وأحصل على خطأ أمان على الرغم من تعيين allowTaint إلى true

لا يوجد حل على حد علمي ، ولكن لدي حل بديل: قم بتغيير كل صورة إلى base64. بهذه الطريقة ، يمكنك عرضها في لوحة الرسم على الرغم من أنها في الأصل من مجال مختلف.

هل رأيت هذا: CORS_enabled_image

إذا كان مصدر المحتوى الأجنبي هو HTML ، محاولة استرداد محتويات اللوحة غير مسموح بها.

بمجرد رسم أي بيانات تم تحميلها من مصدر آخر دون موافقة CORS في لوحة الرسم ، تصبح اللوحة ملوثة.

أستخدم خيارات التكوين مثل هذا:

html2canvas(document.body, {
    allowTaint: true,
    foreignObjectRendering: true
});

مرحبًا ، لقد واجهنا نفس المشكلة. لقد اتبعنا اقتراح

إذا وجد شخص ما أنه مفيد كان الحل:

      html2canvas(document.body, {
        proxy: this._proxyURL,
        allowTaint: true,
        onclone: (cloned) => convertAllImagesToBase64(this._proxyURL, cloned),
      }).then((canvas) => {
        this._postmessageChannel.send(`get.screenshot:${canvas.toDataURL('image/png')}`);
      });

حيث تكون الوظيفة المساعدة convertAllImagesToBase64 هي:

const convertAllImagesToBase64 = (proxyURL, cloned) => {
  const pendingImagesPromises = [];
  const pendingPromisesData = [];

  const images = cloned.getElementsByTagName('img');

  for (let i = 0; i < images.length; i += 1) {
    // First we create an empty promise for each image
    const promise = new Promise((resolve, reject) => {
      pendingPromisesData.push({
        index: i, resolve, reject,
      });
    });
    // We save the promise for later resolve them
    pendingImagesPromises.push(promise);
  }

  for (let i = 0; i < images.length; i += 1) {
    // We fetch the current image
    fetch(`${proxyURL}?url=${images[i].src}`)
      .then((response) => response.json())
      .then((data) => {
        const pending = pendingPromisesData.find((p) => p.index === i);
        images[i].src = data;
        pending.resolve(data);
      })
      .catch((e) => {
        const pending = pendingPromisesData.find((p) => p.index === i);
        pending.reject(e);
      });
  }

  // This will resolve only when all the promises resolve
  return Promise.all(pendingImagesPromises);
};

export { convertAllImagesToBase64 };

بالمناسبة ، هذه هي الاختبارات لهذه الوظيفة المساعدة (نحن نستخدم jest لاختبار wrting وحزم mockFetch):

import { convertAllImagesToBase64 } from '../images';

fetch.resetMocks();

// Mock fetch to respond different for each image so we can assert that the image return the correct response
// Also make one of the response be delayed (2 seconds) to simulate the response is not in the same order we do the call (network latency, image size, etc)
fetch.mockImplementation((url) => {
  if (url.includes('imagesrc1')) {
    return Promise.resolve(new Response(JSON.stringify('data:image/png;base64,1')));
  } else if (url.includes('imagesrc2')) {
    return new Promise((resolve) => setTimeout(resolve(new Response(JSON.stringify('data:image/png;base64,2'))), 2000));
  } else if (url.includes('imagesrc3')) {
    return Promise.resolve(new Response(JSON.stringify('data:image/png;base64,3')));
  }
  return Promise.resolve(new Response(JSON.stringify('')));
});

const mocksImages = [
  { id: 1, src: 'imagesrc1' },
  { id: 2, src: 'imagesrc2' },
  { id: 3, src: 'imagesrc3' },
];

const mockClone = {
  getElementsByTagName: jest.fn(() => mocksImages),
};

describe('utils/images', () => {  
  it('convertAllImagesToBase64. Expect to call 3 times to the correct enpoint using the image source', async () => {
    const allPromises = convertAllImagesToBase64('http://localhost/fake_proxy', mockClone);

    // Expect the clone elements gets all the image tags
    expect(mockClone.getElementsByTagName).toBeCalledWith('img');

    allPromises.then(() => {
      // Expect to have done the 3 fetch calls and with the correct params
      expect(fetch).toBeCalledTimes(3);
      expect(fetch).toHaveBeenNthCalledWith(1, 'http://localhost/fake_proxy?url=imagesrc1');
      expect(fetch).toHaveBeenNthCalledWith(2, 'http://localhost/fake_proxy?url=imagesrc2');
      expect(fetch).toHaveBeenNthCalledWith(3, 'http://localhost/fake_proxy?url=imagesrc3');

      // Expect that our images where updated properly
      expect(mocksImages).toContainEqual({
        id: 1, src: 'data:image/png;base64,1',
      });
      expect(mocksImages).toContainEqual({
        id: 2, src: 'data:image/png;base64,2',
      });
      expect(mocksImages).toContainEqual({
        id: 3, src: 'data:image/png;base64,3',
      });
    });
  });
});

روبي الخلفية enpdoint:

require 'base64'
require 'net/http'

module Api
  module V1
    class ImageProxyController < ApiController
      def index
        url   = URI.parse(params[:url])
        image = Net::HTTP.get_response(url)

        render json: data_url(image).to_json, callback: params[:callback]
      end

      private

        def data_url(image)
          "data:#{image.content_type};base64,#{Base64.encode64(image.body)}"
        end

    end
  end
end

آمل أن يجد شخص ما هذا مفيدًا. آمل أن يساعد ذلك شخصًا ما على عدم استثمار الكثير من الوقت كما فعلنا لإصلاح ذلك بشكل صحيح.

إذا كنت تستطيع أن ترى أي تحسن يرجى اقتراح.
يعتبر.

إذا كنت تحب أدناه ، فماذا سيحدث؟

const TempImage = window.Image

 const Image = function() {
        const img = new TempImage()
        img.crossOrigin = 'anonymous'
        return img
 }

وجدت حلا وهو يعمل

  1. أثناء استدعاء html2canvas ، مرر useCORS إلى true
    html2canvas (selectorElement ، {useCORS: true} ). ثم (canvas => {
    //قم بعمل ما
    }) ؛

  2. ملف html2canvas.js الصحيح. هناك خطأ مطبعي
    غيّر "مجهول" إلى "مجهول" في كتلة if هذه
    إذا (isInlineBase64Image (src) || ​​useCORS) {
    img.crossOrigin = 'مجهول' ؛
    }

var canvasPromise  = html2canvas(document.body, {
                allowTaint: true,
                useCORS: true
            });
canvasPromise.then(function(canvas) {
    document.body.appendChild(canvas);
    console.log(canvas);
    canvas.toDataURL('image/png');
});

تقارير الأخطاء:

غير معلوم (في الوعد) DOMException: فشل تنفيذ "toDataURL" على "HTMLCanvasElement": قد لا يتم تصدير اللوحات الملوثة.

  • تم اختبار إصدار html2canvas باستخدام:
  • Chrome 67.0.3396.99
  • نظام التشغيل Windows 10

ستحتاج إلى استخدام الخاصية "useCORS: true" فقط ، إذا كنت تستخدم الخاصية "allowTaint: true" ، فأنت تعطي تمويجًا لتحويل قماشك إلى لوحة قماشية ملوثة

استخدم هذا:

var canvasPromise  = html2canvas(document.body, {
                useCORS: true
            });
canvasPromise.then(function(canvas) {
    document.body.appendChild(canvas);
    console.log(canvas);
    canvas.toDataURL('image/png');
});

بدلا من هذا:

var canvasPromise  = html2canvas(document.body, {
                allowTaint: true,
                useCORS: true
            });
canvasPromise.then(function(canvas) {
    document.body.appendChild(canvas);
    console.log(canvas);
    canvas.toDataURL('image/png');
});

مرحبًا ، عمل رائع لـ html2canvas.

للأسف أنا أواجه نفس المشكلة ، هل قام أحد بحل هذه المشكلة؟
جربت بالفعل motarock وكل ما قبل ذلك ، بالإضافة إلى التوليفات ، إلخ. الصورة بيضاء بدون أي شيء.

downloadQRCode = (fileName) => {
    html2canvas(document.getElementById('generated-qr-code'), {
      useCORS: true,
      // allowTaint: false,
      // logging: true,
    }).then((canvas) => {
      // document.body.appendChild(canvas); // checking
      const data = canvas.toDataURL('image/jpeg');
      const element = document.createElement('a');
      element.setAttribute('href', data);
      element.setAttribute('download', fileName + '.jpeg');
      document.body.appendChild(element);
      element.click();
      // document.body.removeChild(element);
      console.log("%c data", "font-size:2em;", data, fileName);
      console.log("%c canvas", "font-size:2em;", canvas );
      this.setState({
        imageSrc: data // setting the src of a img tag to check the result. Nothing in it either..
      })
    });

شكرا لك مقدما

لدي أيضا نفس القضايا.
يمكن لأي شخص إصلاح هذه المشكلة؟

:( نفس المشكلة. لدينا html مع svg المتداخلة ولن يتم عرضها

جربت بالفعل motarock وكل ما قبل ذلك ، بالإضافة إلى التوليفات ، إلخ. الصورة بيضاء بدون أي شيء.

لدي هذه المشكلة عندما لا أستخدم SSL ، حيث يعمل SSL بشكل مثالي

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات