谷歌文档查看器返回 204 响应,不再工作,替代方案?
Posted
技术标签:
【中文标题】谷歌文档查看器返回 204 响应,不再工作,替代方案?【英文标题】:Google Docs viewer returning 204 responses, no longer working, alternatives? 【发布时间】:2017-03-17 18:40:07 【问题描述】:美国东部时间 2016 年 11 月 16 日上午 9:53 更新
尽管 Google 声称已“修复”该问题,但似乎仍有许多人看到 204 响应。当我自己测试文档加载 50 次时,其中 3 次 Google 返回了 204 响应。
请访问此 URL 并发表关于您的不满的评论,以便我们最终让 Google 彻底解决和解决问题:https://productforums.google.com/forum/?utm_medium=email&utm_source=footer#!msg/docs/hmj39HMDP1M/SR2UdRUdAQAJ
美国东部时间 2016 年 11 月 4 日下午 6:01 更新
服务似乎已启动并再次运行!感谢 Google Docs 解决了这个问题并回复了我的推文。希望它也适用于你们所有人。
美国东部时间 2016 年 11 月 4 日下午 3:33 更新
https://productforums.google.com/forum/#!msg/docs/hmj39HMDP1M/X6a8xJwLBQAJ 发布了一个更新,这似乎表明对该服务的支持可能正在恢复和/或最终存在导致意外结果的问题。敬请关注。请参阅下面的评论:
Stack Overflow 上的原创文章从这里开始
我们的网络软件使用并依赖 Google 文档查看器服务将文档嵌入我们的网站(通过 iframe),并让我们的客户能够查看文档,而无需打开单独的应用程序(通过访问 URL)。该功能由 Google 提供了很长一段时间,并且运行良好!
示例查看器 URL:
https://docs.google.com/viewer?url=http://www.pdf995.com/samples/pdf.pdf
然而,我们开始注意到,我们尝试加载的文件只会很少加载。我们最初认为他们的服务器存在问题,因此开始调查我们收到的标头响应。特别是,我们注意到几乎每个发出的请求都返回 204 No Content 响应。我们偶尔会收到 200 条回复。
以下是我们收到的 204 条回复之一的示例:
这是我们收到的 200 条回复之一的示例(非常罕见):
之后,我在 Google 上搜索了与 Google 查看器服务相关的 204 个问题。我最终进入了这个页面https://productforums.google.com/forum/#!msg/docs/hmj39HMDP1M/X6a8xJwLBQAJ,这似乎表明谷歌突然突然停止了这项服务。这是该讨论的屏幕截图(截至本文发布时)。
鉴于 Google 的“专家”回复了此人的类似询问;看来他们已经正式完全放弃了对查看器服务的支持。
我的问题如下:
是否有其他人确切知道 Google 是否正式终止了对 Google 查看器服务的支持?
有谁知道更新后的类似 Google 产品/服务(可能是 Google Drive?),它允许人们做与上面提到的查看器服务完全相同的事情?理想情况下,我想要一个简单的 URL,我可以在其中引用不必存在于 Google 服务器上但仍可以驻留在我的服务器上的外部文档。
您可以建议哪些其他类似的和免费服务允许我将 Word 文档、Excel 文档、PowerPoint 文档和 PDF 等文档嵌入到允许用户的网站中无需在系统上实际安装这些应用程序即可在浏览器中查看文档。
作为最后一点,我只想说,尽管谷歌做得很好,但他们可以提供人们长期依赖的服务却突然拔掉插头,这令人难以置信的愤怒、沮丧和烦人在上面。我敢肯定,除了我自己之外,还有很多其他人永远不会打扰表达对这种决定的担忧。谷歌纠正了这个问题,并且在我的书中仍然很好:-)
提前感谢您的回答!
【问题讨论】:
值得注意的是,Google 从未将其作为服务提供给开发人员,而且它不是官方支持的 API 的一部分。找到有效的端点与 Google 提供服务不同,在不受支持的端点上构建会带来风险。 很公平。然而,他们心照不宣地知道,成千上万的人依赖该服务并将其集成到他们的应用程序中。 除此之外,微软还提供类似的服务并积极推广:products.office.com/en-US/office-online/…。它是谷歌服务的劣质产品,因为它不支持 PDF 渲染。我根本看不出谷歌有任何理由将其关闭。它只会将人们推向竞争对手的服务。我很乐意支付月费以继续使用 Google。 2017 年 3 月。仍然没有修复 2019 年 7 月。返回 204 【参考方案1】:我运行的服务也依赖于嵌入 Google Doc Viewer,我也遇到了这个问题。我找不到任何其他类似的服务(免费或其他)。
我想出了一个“技巧”,可以帮助您摆脱使用 Google 文档查看器的麻烦。它确实需要 JQuery。我所做的是每 2 秒刷新一次 iframe,直到它最终正确加载。我还用加载 gif 覆盖 iframe 以隐藏不断刷新。我的代码:
<style>
.holds-the-iframe
background:url(/img/loading.gif) center center no-repeat;
</style>
<div class="holds-the-iframe">
<iframe id="iframeID" name="iframeID" src="https://docs.google.com/viewerng/viewer?url=www.example.com&embedded=true"></iframe>
</div>
<script>
function reloadIFrame()
document.getElementById("ifm").src=document.getElementById("iframeID").src;
timerId = setInterval("reloadIFrame();", 2000);
$( document ).ready(function()
$('#iframeID').on('load', function()
clearInterval(timerId);
console.log("Finally Loaded");
);
);
</script>
【讨论】:
我想过做类似的事情。但是,该解决方案需要更长的时间才能加载,并且鉴于他们已表示将逐步淘汰该解决方案,因此也不能保证将来可以正常工作。我完全不知道为什么他们会在知道人们使用它的情况下将其关闭。这不适用于我,但有大量的 Wordpress 插件使用它,所以我确信很多网站都受到了影响。 我同意,这很烦人。另一个“解决方案”是使用 Microsoft 等效的https://view.officeapps.live.com/op/embed.aspx?src=[OFFICE_FILE_URL]
(仅适用于办公文档)来显示 DOC 和 DOCX 文件以及类似 PDF.JS 的东西来处理 PDF。或者将所有文件转换为 PDF 并使用 PDF.JS。
谢谢。我看到了微软的等价物,但也注意到它无法呈现 PDF。谷歌查看器在它所做的事情上是如此完美。我在 [at]GoogleDocs 和 [at]jrochelle 发了推文,要求做出解释并鼓励他们将服务还给我们。也许如果他们看到足够多的愤怒,他们会考虑改变方向。
@ArtGeigel 如果你没有忘记,如果你发现了什么有趣的事情,请告诉我!
当然是@Cellydy!有些人一直在转发我的投诉,所以也许我们最终会受到他们的关注。我会及时通知你。【参考方案2】:
我使用 Google 查看器作为我们内部管理系统的副本查看器,我们通常只上传 PDF 和图像文件,因此作为一个一体化解决方案非常出色,可以全面工作(移动设备、桌面设备等) )。然而随着它变得越来越不可靠,我有了创意。
如果在上传后查看 PDF,我的解决方案是使用 imagick 生成并保存 PDF 的 JPG 版本。与其对所有上传的 PDF 进行批处理,不如仅在访问它们时对其进行转换。
我的理由是:
-
我的用户池非常小,因此文件类型很容易管理
上传后需要再次查看每个 PDF 的可能性几乎为零,因此仅在需要报告时创建。
我需要一种通过移动设备查看文件的可靠方式。 ios 和 android 在浏览器 PDF 查看器中表现不佳,而且每个人都知道在 iOS 设备上查看 PDF 有多么麻烦(iBooks 有人吗?)
查看文件并创建 pdf 的 jpg 版本后,只要用户查看该文件,就会使用该文件代替 PDF。不漂亮但肯定有效,我承认有一个加倍的元素但是我没有任何存储限制。原始文件也没有被修改,因此它也可以用作第三远程备份。这不是设计使然,而是一个快乐的巧合。
如果对您有用,请随意使用下面的代码。可能有更优雅的方法可以做到这一点,但对于我的目的和用户来说,这很好。
$_thumbnail = 'files/thumbnails/'.$_section.'/'.$_fileName.'.jpg';
if (!file_exists($_thumbnail))
$_file = 'files/'.$_section.'/'.$_fileName;
$imagePreview = new imagick();
$imagePreview->setResolution(300, 300);
$imagePreview->readimage($_file);
$imagePreview->setImageFormat( "jpg" );
$imagePreview->writeImage('files/thumbnails/'.$_section.'/'.$_fileName.'.jpg');
echo '<img src="/files/thumbnails/'.$_section.'/'.$_fileName.'.jpg" />';
else
echo '<img src="/files/thumbnails/'.$_section.'/'.$_fileName.'.jpg" />';
【讨论】:
【参考方案3】:使用 Reactjs 的简单解决方案/hack,但可以轻松实现到任何其他库/vanilla。
与一个基本概念一起使用:尝试加载 - 如果 onload 完成,则清除间隔,否则每 3 秒尝试再次加载。完美运行
(我已经编辑了我自己的代码,所以它包含最少的代码,所以没有测试)
var React = require('react');
export default class IframeGoogleDocs extends React.Component
constructor(props)
super();
this.bindActions();
bindActions()
this.updateIframeSrc = this.updateIframeSrc.bind(this);
this.iframeLoaded = this.iframeLoaded.bind(this);
iframeLoaded()
clearInterval(this.iframeTimeoutId);
getIframeLink()
return `https://docs.google.com/gview?url=$this.props.url`; // no need for this if thats not dynamic
updateIframeSrc()
this.refs.iframe.src = this.getIframeLink();
componentDidMount()
this.iframeTimeoutId = setInterval(
this.updateIframeSrc, 1000 * 3
);
render()
return (
<iframe onLoad=this.iframeLoaded onError=this.updateIframeSrc ref="iframe" src=this.getIframeLink()></iframe>
);
【讨论】:
对我来说真的很有帮助,只是 safari 没有激活 onError 存在问题。在此处查看解决方案:***.com/a/62791842/9702000 试过这段代码,但没有用。你能分享你的完整组件吗?【参考方案4】:我解决了这个问题如下。如果未加载谷歌查看器,请重新启动 iframe。
function reloadIFrame()
var iframe = document.getElementById("iFrame");
console.log(frame.contentDocument.URL); //work control
if(iframe.contentDocument.URL == "about:blank")
iframe.src = iframe.src;
var timerId = setInterval("reloadIFrame();", 2000);
$( document ).ready(function()
$('#menuiFrame').on('load', function()
clearInterval(timerId);
console.log("Finally Loaded"); //work control
);
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<iframe id="iFrame" src="https://docs.google.com/gview?url=http:exemple.pdf?entryPoint=projectimage&id=1bef4781-5eb5-60b0-8f0b-5426c9877ebe&type=apoll_Web_Project_Files&embedded=true" style="width:718px; height:700px;" frameborder="0"></iframe>
【讨论】:
【参考方案5】:我能够让它与 Тетяна Волошка 的答案一起使用,但是我不得不删除 if 语句,因为
这个
iframe.contentDocument.URL == "about:blank"
引起
DOMException: Blocked a frame with origin from accessing a cross-origin frame.
我不太清楚为什么这会为我解决这个问题。也许 2 秒的延迟允许我页面上的所有其他内容加载并消除嵌入 pdf 加载的任何冲突,但是如果没有跨域问题,我还能如何获取内容文档?
【讨论】:
检查此解决方案***.com/a/70093907/8371889。希望对你有帮助【参考方案6】:这是功能组件中的一个反应示例
import React, useEffect, useRef, useState from "react";
type IframeGoogleDocsProps =
url: string,
className?: string
;
export default function IframeGoogleDoc(url, className: IframeGoogleDocsProps)
const [iframeTimeoutId, setIframeTimeoutId] = useState(undefined);
const iframeRef = useRef(null);
useEffect(()=>
const intervalId = setInterval(
updateIframeSrc, 1000 * 3
);
setIframeTimeoutId(intervalId)
,[]);
function iframeLoaded()
clearInterval(iframeTimeoutId);
function getIframeLink()
return `https://docs.google.com/gview?url=$url&embedded=true`;
function updateIframeSrc()
if(iframeRef.current)
iframeRef.current.src = getIframeLink();
return (
<iframe
className=className
onLoad=iframeLoaded
onError=updateIframeSrc
ref=iframeRef
src=getIframeLink()
/>
);
【讨论】:
必须进行一些更改才能使其正常工作 - gist.github.com/RusseII/62a304c29af402292ef4c57a1cf1a988 请注意,此 gview 目前正在给我们带来问题。网速慢的用户将永远存在加载问题。似乎没有办法解决。 要摆脱无限加载问题,您可以增加间隔时间,或者每次加载失败时将等待时间加倍。不漂亮,但会确保它最终能 100% 的工作。 @RussellRatcliffe 我认为某种退避机制肯定是更好的方法。【参考方案7】:我想我也会在这里分享this solution,因为上面的答案对于大型文档不会有效:加载事件在 iFrame 开始加载后的几秒钟内不会触发,所以你可能会结束无限循环。更好的解决方案是同时检查 iFrame 主体的大小。
【讨论】:
将答案添加到您自己的帖子中;不要仅仅链接到它。 嘿@HappyFace。我似乎找不到针对通过链接共享答案的具体指南(当然,在适当的上下文中)。我认为这是可取的,以避免重复的内容,并且对于答案的任何潜在的未来修改只有 1 个参考点。如果您有其他看法,请告诉我。 meta.***.com/questions/251006/…【参考方案8】:花了很多时间终于找到了解决办法!!!
最好的选择是使用 Adobe 提供的免费服务,PDF embed API。
HERE
-
创建您的项目
获取您的客户 ID
添加您的域(它只会
为该域工作)
【讨论】:
这不只是为了处理 PDF 吗? Google 查看器支持 IMO 使其更有用的所有常见文档类型。 是的。你说的对。因为是Adobe所以只支持PDF。【参考方案9】:我可能有一个愚蠢的问题,但是,为什么我们要检查文档是否已加载? 在我们得到 200 之前捕获响应 204 并刷新并不容易(然后我们确定该文档已加载):)
【讨论】:
从我这里检查这个解决方案***.com/a/70093907/8371889。希望对你有帮助【参考方案10】:我发现Byron Dokimakis
的解决方案有效。
但是,有些人在尝试访问跨源 iframe 时可能会遇到此错误。
DOMException: 阻止具有源的框架访问跨域框架。
我找到了一种解决此问题的骇人听闻的方法。 我注意到如果 google 文档页面为空 (204),则不会显示跨域异常。
所以我们可以在这里使用try catch
这是我的代码示例:
const PdfViewer = ( url ) =>
const iframeRef = useRef(null);
const interval = useRef();
const pdfUrl = createGdocsUrl(url);
const [loaded, setLoaded] = useState(false);
const clearCheckingInterval = () =>
clearInterval(interval.current);
;
const onIframeLoaded = () =>
clearCheckingInterval();
setLoaded(true);
;
useEffect(() =>
interval.current = setInterval(() =>
try
// google docs page is blank (204), hence we need to reload the iframe.
if (iframeRef.current.contentWindow.document.body.innerhtml === '')
iframeRef.current.src = pdfUrl;
catch (e)
// google docs page is being loaded, but will throw CORS error.
// it mean that the page won't be blank and we can remove the checking interval.
onIframeLoaded();
, 4000); // 4000ms is reasonable time to load 2MB document
return clearCheckingInterval;
, []);
return (
<div className=css['pdf-iframe__wrapper']>
<iframe
ref=iframeRef
className=css['pdf-iframe__inside']
frameBorder="no"
onLoad=onIframeLoaded
src=pdfUrl
title="PDF Viewer"
/>
!loaded && (
<div className=css['pdf-iframe__skeleton']>
<Skeleton rectRadius= rx: 0, ry: 0 />
</div>
)
</div>
);
;
【讨论】:
以上是关于谷歌文档查看器返回 204 响应,不再工作,替代方案?的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 浏览器上嵌入谷歌文档查看器 iframe
如何在swagger codegen中处理多种响应/返回类型(204为空,400为非空等)?