Skip to content

Instantly share code, notes, and snippets.

@rpggio
Last active October 22, 2024 03:33
Show Gist options
  • Save rpggio/5f521e1f15f969529f4fe506fc0d1c0a to your computer and use it in GitHub Desktop.
Save rpggio/5f521e1f15f969529f4fe506fc0d1c0a to your computer and use it in GitHub Desktop.
Automatic retry for iframe loading (workaround for Google Doc Viewer 204 issue)
function GoogleDocFrame({ url }: { url: string }) {
const frameRef = useRef<HTMLIFrameElement>(null)
const viewerUrl = `https://docs.google.com/viewer?embedded=true&url=${url}`
let cancel: () => void | undefined
useEffect(() => {
cancel = setFrameSrcWithRetry(frameRef.current!, viewerUrl, true)
// unmount
return () => {
if (cancel) {
cancel()
}
}
}, [url])
return <iframe ref={frameRef} />
}
/**
* Set src for an iframe. If the iframe does not load, try setting src again to
* force reload. Repeat for given number of times.
* This can be used as a workaround for Google doc viewer 204 issue: https://tinyurl.com/y7zx253q
* Viewer URL pattern: [https://docs.google.com/viewer?embedded=true&url=PUBLIC_URL]
* @param iframe
* @param src
* @param maxRetries - Max number of time to try frame reload
* @param initialDelayMs - Initial delay time to use. Exponential easing is used
* for additional cycles.
*/
export default function setFrameSrcWithRetry(
iframe: HTMLIFrameElement,
src: string,
maxRetries = 4,
initialDelayMs = 3000) {
console.log('setting frame source')
let retriesLeft = maxRetries
let loaded = false
let timeoutRef: any = null
let delayMs = initialDelayMs
const cancel = () => {
retriesLeft = 0
if (timeoutRef) {
clearTimeout(timeoutRef)
}
}
const setRetry = () => {
setTimeout(() => {
if (!loaded && retriesLeft-- > 0) {
log.info('forcing iframe refresh')
iframe.src = src
setRetry()
delayMs *= 1.5
}
}, delayMs)
}
iframe.onload = () => {
loaded = true
cancel()
}
iframe.src = src
setRetry()
return cancel
}
@opiispanen
Copy link

I actually converted this to Vue version with the help of ChatGPT and it works fine! 😃

I just wonder what is the reason of the 204 No content, it looks like if the same request is done often they just respond with 204. Is there a better way to do this in 2024, or embedding PDF in general (especially on mobile)?

@bangank36
Copy link

bangank36 commented Oct 22, 2024

I think server overload will result in 204 respond, as this is an undocumented feature from Google, we can't expect that much :(
If your pdf support CORS, I'd say using pdf.js for a better viewer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment