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

跨路由传递图片失败排查及替代方案咨询

问题原因分析
  1. Blob URL的会话限制:URL.createObjectURL()生成的URL与当前页面会话绑定,仅在创建它的页面上下文内有效。通过路由query参数传递后,新路由页面属于独立上下文,该URL已失效,导致图片无法加载,且因是合法但无效的URL,不会触发报错。
  2. 状态存储逻辑错误:直接将<img> JSX元素存入useState不符合React状态管理规范,状态应存储数据(如文件、base64字符串),而非UI元素,渲染时再根据数据生成UI。
可行的跨路由传图方案

方案1:全局状态管理(推荐)

使用React Context、Zustand、Redux等工具存储文件数据,跨路由直接读取:

示例(React Context)

  1. 创建文件上下文:
import { createContext, useContext, useState } from 'react';

const FileContext = createContext();

export function FileProvider({ children }) {
  const [selectedFile, setSelectedFile] = useState(null);
  return (
    <FileContext.Provider value={{ selectedFile, setSelectedFile }}>
      {children}
    </FileContext.Provider>
  );
}

export function useFileContext() {
  return useContext(FileContext);
}
  1. 上传路由存储文件:
import { useFileContext } from './FileContext';
import { useRouter } from 'next/router';

function UploadPage() {
  const { setSelectedFile } = useFileContext();
  const router = useRouter();

  const handleFileSelect = (e) => {
    const file = e.target.files[0];
    setSelectedFile(file);
    router.push('/');
  };

  return <input type="file" onChange={handleFileSelect} />;
}
  1. 目标路由渲染图片:
import { useFileContext } from './FileContext';
import { useState, useEffect } from 'react';

function TargetPage() {
  const { selectedFile } = useFileContext();
  const [imageUrl, setImageUrl] = useState(null);

  useEffect(() => {
    if (selectedFile) {
      const url = URL.createObjectURL(selectedFile);
      setImageUrl(url);
      return () => URL.revokeObjectURL(url); // 组件卸载时释放资源
    }
  }, [selectedFile]);

  return imageUrl ? <img src={imageUrl} alt="Story" /> : null;
}

方案2:路由状态传递(临时场景适用)

利用路由state属性传递数据(不暴露在URL中,比query更安全):

上传路由代码:

import { useRouter } from 'next/router';

function UploadPage() {
  const router = useRouter();

  const handleFileSelect = (e) => {
    const file = e.target.files[0];
    // 将文件转成base64(适合小文件)
    const reader = new FileReader();
    reader.onload = () => {
      router.push({
        pathname: '/',
        state: { imageBase64: reader.result }
      });
    };
    reader.readAsDataURL(file);
  };

  return <input type="file" onChange={handleFileSelect} />;
}

目标路由代码:

import { useRouter } from 'next/router';

function TargetPage() {
  const router = useRouter();
  const imageBase64 = router.state?.imageBase64;

  return imageBase64 ? <img src={imageBase64} alt="Story" /> : null;
}

方案3:本地存储(持久化场景适用)

将文件转成base64存入sessionStorage或localStorage,目标路由读取后渲染:

上传路由代码:

import { useRouter } from 'next/router';

function UploadPage() {
  const router = useRouter();

  const handleFileSelect = (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();
    reader.onload = () => {
      sessionStorage.setItem('uploadedImage', reader.result);
      router.push('/');
    };
    reader.readAsDataURL(file);
  };

  return <input type="file" onChange={handleFileSelect} />;
}

目标路由代码:

import { useState, useEffect } from 'react';

function TargetPage() {
  const [imageBase64, setImageBase64] = useState(null);

  useEffect(() => {
    const base64 = sessionStorage.getItem('uploadedImage');
    if (base64) {
      setImageBase64(base64);
      sessionStorage.removeItem('uploadedImage'); // 用完清理,避免残留
    }
  }, []);

  return imageBase64 ? <img src={imageBase64} alt="Story" /> : null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:15:08