You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取数据后以Blob形式在当前窗口打开PDF替代PDFViewer

实现方案

要替换PDFViewer,在获取接口数据后直接在当前标签页以Blob形式打开PDF,可以通过以下两种方式实现:

方式一:使用renderToBlob直接生成并跳转

这种方式无需BlobProvider,直接调用@react-pdf/renderer提供的renderToBlob方法生成PDF Blob,再通过window.location.href跳转到Blob URL。

修改后的完整代码:

import { OrderDocument } from '@/components'
import { toast } from '@/components/ui/use-toast'
import { useAuthContext } from '@/context/authContext'
import { getFetch } from '@/hooks/fetchData'
import { renderToBlob } from '@react-pdf/renderer'
import { useEffect, useState } from 'react'
import { ImSpinner6 } from "react-icons/im";
import { useNavigate, useParams } from 'react-router-dom'

const OrderReceipt = () => {
    const { orderId } = useParams()
    const { user } = useAuthContext()
    const token = user?.apikey?.token

    const [orderData, setOrderData] = useState();
    const [isLoading, setIsLoading] = useState(false);
    const [isError, setIsError] = useState(null);

    const navigate = useNavigate()

    useEffect(() => {
        setIsLoading(true)
        getFetch(token, `/orders/${orderId}`)
            .then((res) => {
                setOrderData(res.data?.data)
            })
            .catch((e) => {
                setIsError(e?.response?.data?.message)
                toast({
                    variant: 'destructive',
                    description: e.response.data.message,
                });
                navigate('/')
            })
            .finally(() => setIsLoading(false))
    }, [])

    // 数据加载完成后生成PDF并在当前页打开
    useEffect(() => {
        if (!orderData) return
        
        renderToBlob(<OrderDocument data={[orderData]} />)
            .then((blob) => {
                const pdfUrl = URL.createObjectURL(blob)
                // 替换当前页地址为PDF Blob URL
                window.location.href = pdfUrl
                // 延迟释放URL资源,避免跳转时资源被回收
                setTimeout(() => URL.revokeObjectURL(pdfUrl), 1000)
            })
            .catch(() => {
                toast({
                    variant: 'destructive',
                    description: 'PDF生成失败,请重试',
                })
            })
    }, [orderData])

    if (isLoading) {
        return <div className='w-full h-screen flex-center'>
            <ImSpinner6 className="animate-spin text-gray-500  size-24" />
        </div>
    }
    if (isError) {
        return <div className='w-full h-screen flex-center'>
            <h2>unexpected error</h2>
        </div>
    }

    // 数据加载完成后会立即跳转,此处无需额外渲染内容
    return null
}

export default OrderReceipt

方式二:基于BlobProvider实现跳转

如果你更习惯使用之前的BlobProvider,可以通过在BlobProvider内部获取生成的URL,再触发当前页跳转:

替换原组件中return部分的代码即可:

return (
    <>
        {isLoading && <div className='w-full h-screen flex-center'>
            <ImSpinner6 className="animate-spin text-gray-500  size-24" />
        </div>}
        {isError && <div className='w-full h-screen flex-center'>
            <h2>unexpected error</h2>
        </div>}
        {orderData && (
            <BlobProvider document={<OrderDocument data={[orderData]} />}>
                {({ url }) => {
                    // 组件挂载后执行跳转
                    useEffect(() => {
                        window.location.href = url
                        return () => URL.revokeObjectURL(url)
                    }, [url])
                    // 无需渲染可见内容
                    return null
                }}
            </BlobProvider>
        )}
    </>
)

注意事项

  • 生成Blob URL后,记得调用URL.revokeObjectURL()释放资源,避免内存泄漏
  • 若浏览器阻止自动跳转,可添加手动触发按钮,但上述方案已满足自动在当前页打开的需求
  • 确保OrderDocument组件能正确接收data并渲染PDF内容

内容的提问来源于stack exchange,提问作者abdo_me

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 08:07:43