【问题标题】:Why is an image from google drive not displayed on google site through an embeded html, made using Altair (vega-lite)为什么使用 Altair (vega-lite) 制作的来自谷歌驱动器的图像未通过嵌入式 html 显示在谷歌网站上
【发布时间】:2022-01-16 13:02:47
【问题描述】:

当我像这样嵌入时,我很难理解为什么来自谷歌驱动器(私人或共享给公共)的图像会毫无问题地显示在谷歌网站上:

<!DOCTYPE html>
<html>

<body>
    <img src="https://drive.google.com/uc?export=view&id=0B6wwyazyzml-OGQ3VUo0Z2thdmc" width="500">
</body>

</html>

在这里,谷歌驱动器上的图像存储在https://drive.google.com/uc?export=view&id=0B6wwyazyzml-OGQ3VUo0Z2thdmc 并公开共享。图片的文件ID为0B6wwyazyzml-OGQ3VUo0Z2thdmc

既然显示了图片,就意味着可以从google站点的google drive中读取图片。

但是当我使用Altair (Vega-lite) 生成 html 时,使用以下最少代码:

import altair as alt
import pandas as pd
source = pd.DataFrame({"img": ["https://drive.google.com/uc?export=view&id=0B6wwyazyzml-OGQ3VUo0Z2thdmc",]})
chart=alt.Chart(source).mark_image(width=100,height=100,).encode(x=alt.value(0),y=alt.value(0),url='img')
chart.save('test/gdrive.html')

html的内容:

<!DOCTYPE html>
<html>
<head>
  <style>
    .error {
        color: red;
    }
  </style>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega@5"></script>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega-lite@4.8.1"></script>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm//vega-embed@6"></script>
</head>
<body>
  <div id="vis"></div>
  <script>
    (function(vegaEmbed) {
      var spec = {"config": {"view": {"continuousWidth": 400, "continuousHeight": 300}}, "data": {"name": "data-f41fe47a6561a1d8f01ad1fd7b81dffd"}, "mark": {"type": "image", "height": 100, "width": 100}, "encoding": {"url": {"type": "nominal", "field": "img"}, "x": {"value": 0}, "y": {"value": 0}}, "$schema": "https://vega.github.io/schema/vega-lite/v4.8.1.json", "datasets": {"data-f41fe47a6561a1d8f01ad1fd7b81dffd": [{"img": "https://drive.google.com/uc?export=view&id=0B6wwyazyzml-OGQ3VUo0Z2thdmc"}]}};
      var embedOpt = {"mode": "vega-lite"};

      function showError(el, error){
          el.innerHTML = ('<div class="error" style="color:red;">'
                          + '<p>JavaScript Error: ' + error.message + '</p>'
                          + "<p>This usually means there's a typo in your chart specification. "
                          + "See the javascript console for the full traceback.</p>"
                          + '</div>');
          throw error;
      }
      const el = document.getElementById('vis');
      vegaEmbed("#vis", spec, embedOpt)
        .catch(error => showError(el, error));
    })(vegaEmbed);

  </script>
</body>
</html>

图片未显示。

我想知道为什么会这样。

为了快速诊断,我查看了 vega-editor 的 LOGS 选项卡。在那里我看到了这个错误:[Error] Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.

【问题讨论】:

  • 在 vega-editor 的 LOGS 选项卡中,我看到了这个错误:[Error] Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.
  • 您应该将该信息添加到您的问题中(编辑问题并将其放入)。
  • 您能否提供一个未呈现的公共驱动器图像 URL 的示例?
  • 嗨@jakevdp,我刚刚添加了一个驱动器图像URL(我在一个关于在谷歌站点中嵌入谷歌驱动器图像的问题中看到:stackoverflow.com/a/52067077/3521099
  • 嗨@psmears,我刚刚在我的问题中添加了错误消息。

标签: html google-drive-api altair vega-lite google-sites-2016


【解决方案1】:

简短的回答:由于您的浏览器的跨域安全功能,这不起作用,唯一的解决方法是将图像托管在其他地方。

长版:如果您在查看图表时打开 Javascript 控制台日志,您会看到如下内容:

Access to image at 'https://drive.google.com/uc?export=view&id=0B6wwyazyzml-OGQ3VUo0Z2thdmc' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这表明在您的页面上运行的脚本正在尝试访问故意禁止脚本访问的资源。如果不更改 Google Drive 内容上的 CORS 标头,就无法解决此问题,而且 Google 之所以无法做到这一点是有充分理由的:如果标头设置得更宽松,那么在您访问的任何网页上运行的恶意 javascript 都可能以编程方式从您的 Google 云端硬盘中抓取内容。

所以你必须在别处托管你的图像。

一个简单的替代方法是下载图像并将其托管在托管图表代码的同一台服务器上;例如

from urllib.request import urlretrieve
urlretrieve("https://drive.google.com/uc?export=view&id=0B6wwyazyzml-OGQ3VUo0Z2thdmc", "test/img.jpg")

import altair as alt
import pandas as pd
source = pd.DataFrame({"img": ["img.jpg"]})
chart=alt.Chart(source).mark_image(width=100,height=100,).encode(x=alt.value(0),y=alt.value(0),url='img')
chart.save('test/chart.html')

【讨论】:

  • 非常感谢您的回答。这解释了很多。我实际上是专门使用 google-drive 的,因为我不想在公共领域的其他地方托管图像。 :) 但不幸的是,这是不行的。
  • 作为一个潜在的解决方案,我尝试将图像编码为字节/数据。但是随后 HTML 的大小变得太大而无法将其嵌入到 google-site 中。谷歌网站不允许嵌入大于 1Mb 大小的 html。
  • 所以,我现在正在寻找允许嵌入大型 HTML (webapps.stackexchange.com/q/161819/163839) 的 google-site 替代方案。将图像编码为字节/数据肯定会使 html 渲染速度变慢,但我想这是我目前能想到的唯一解决方案。
猜你喜欢
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多