如何在React应用中正常显示Django REST API返回的图片资源
问题根因
- 逻辑使用错误:
img标签的src属性无法直接识别ajax请求返回的二进制图片数据,且你在初始化useState时调用异步的apiImage方法,没有将请求返回的结果正确存入state,导致img的src为无效值。 - 跨域/路径错误:React和Django运行在不同端口时,相对路径的请求会默认发到React的服务端口,而非Django端口,同时浏览器会拦截跨域请求,导致图片加载失败。
最优解决方案
你的Django接口直接访问即可返回图片,不需要额外封装ajax请求加载,直接将接口完整地址赋值给img的src属性即可,浏览器会自动完成图片请求加载:
function App() { const classes = useStyles() // 存储图片ID,而非请求结果 const [imgId, setImgId] = useState(2) // 替换为你实际的Django服务地址,生产环境可换成部署后的域名 const djangoHost = 'http://127.0.0.1:8000' const ImgChange =(e) =>{ if(e === 'laugh'){ // 替换为laugh对应的图片ID setImgId(3) } if(e === 'smile'){ // 替换为smile对应的图片ID setImgId(2) } } return ( <Grid container display="flex" direction="column" justifyContent="center" alignItems="center" className={classes.grid}> <img src={`${djangoHost}/api/id/${imgId}`} alt='girl' className={classes.img}/> <Paper className={classes.paper} > <Textfield handleWaifuChange={ImgChange}/> </Paper> </Grid> ); }
如果不想在代码里写死Django服务地址,可以在React项目的package.json中添加代理配置:
{ "name": "your-react-project", "version": "0.1.0", "proxy": "http://127.0.0.1:8000", ... }
配置完成后重启React服务,所有相对路径的请求会自动转发到Django服务,img的src直接写/api/id/${imgId}即可。
可选:手动请求二进制流的修改方案
如果你确实需要通过ajax请求拿到图片数据再渲染,需要将返回的二进制流转为Blob URL才能赋值给src,修改代码如下:
- 先调整你的
backendlookup方法,请求图片时指定responseType为blob,避免返回的二进制数据被转为字符串 - 调整组件逻辑:
export function apiImage(imageId,callback) { const endpoint = `id/${imageId}` // 传入responseType配置,axios示例:axios.get(endpoint, {responseType: 'blob'}).then(res => callback(res.data, res.status)) backendlookup('GET', endpoint ,callback, {responseType: 'blob'}) } function App() { const classes = useStyles() const [img, setImg] = useState('') const handleLookup = (response, status) => { if (status === 200) { // 将blob二进制流转为浏览器可识别的临时URL const imageUrl = URL.createObjectURL(response) setImg(imageUrl) } } // 组件挂载后加载默认图片 useEffect(() => { apiImage(2, handleLookup) // 组件卸载时释放临时URL,避免内存泄漏 return () => { if (img) URL.revokeObjectURL(img) } }, []) const ImgChange =(e) =>{ if(e === 'laugh'){ apiImage(3, handleLookup) } if(e === 'smile'){ apiImage(2, handleLookup) } } return ( <Grid container display="flex" direction="column" justifyContent="center" alignItems="center" className={classes.grid}> <img src={img} alt='girl' className={classes.img}/> <Paper className={classes.paper} > <Textfield handleWaifuChange={ImgChange}/> </Paper> </Grid> ); }
Django端跨域配置
前后端端口不同时需要配置Django允许跨域请求:
- 安装依赖:
pip install django-cors-headers - 修改
settings.py配置:
INSTALLED_APPS = [ # ... 其他应用 'corsheaders', ] MIDDLEWARE = [ # 放在最顶部,优先执行 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... 其他中间件 ] # 开发环境可允许所有来源,生产环境替换为你的前端部署地址 CORS_ALLOW_ALL_ORIGINS = True
内容的提问来源于stack exchange,提问作者diabetico
相关产品推荐
相关产品推荐

