Java+React项目上传图片到Amazon S3后无需整页刷新更新显示问题咨询
问题根因
当前上传成功后仅打印日志,没有主动触发前端图片资源的重新拉取逻辑,加上浏览器默认会缓存固定路径的图片资源,所以需要手动触发状态更新才能展示新上传的图片。
解决步骤
1. 调整Dropzone组件,添加上传成功回调
修改Dropzone组件,新增onUploadSuccess属性,上传完成后通知父组件刷新图片:
// 新增onUploadSuccess回调props,用于通知父组件上传完成 function Dropzone({userProfileId, onUploadSuccess}) { const onDrop = useCallback(acceptedFiles => { const file = acceptedFiles[0]; const formData = new FormData(); formData.append("file", file); axios.post(`http://localhost:3021/api/v1/user-profile/${userProfileId}/image/upload`, formData, { headers: { "Content-type": "multipart/form-data" } } ).then(()=>{ console.log("file uploaded") // 触发父组件传入的回调,刷新图片 onUploadSuccess?.() }).catch(err=>{ console.log(err); }) }, [userProfileId, onUploadSuccess]); // 补全依赖项 const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop}) return ( <div {...getRootProps()}> <input {...getInputProps()} /> { isDragActive ? <p>拖放文件到此处 ...</p> : <p>拖放头像到此处,或点击选择头像</p> } </div> ) }
2. 父组件实现图片刷新逻辑
父组件用状态存储图片地址,写拉取最新图片的方法,上传完成后主动调用该方法更新状态,同时给图片地址加时间戳避免浏览器缓存旧资源:
function UserProfile() { const [profileImgUrl, setProfileImgUrl] = useState('') const userProfileId = '当前用户ID' // 拉取最新头像的方法 const fetchLatestImage = async () => { try { const res = await axios.get(`http://localhost:3021/api/v1/user-profile/${userProfileId}/image/download`, { responseType: 'blob' // 指定返回格式为二进制流 }) // 把二进制流转为前端可访问的资源地址 const rawUrl = URL.createObjectURL(res.data) // 加时间戳参数,避免浏览器读取缓存的旧图片 setProfileImgUrl(`${rawUrl}?t=${Date.now()}`) } catch (e) { console.log('拉取图片失败', e) } } // 页面首次加载时拉取初始头像 useEffect(() => { fetchLatestImage() }, [userProfileId]) return ( <div> {/* 展示头像 */} <img src={profileImgUrl} alt="用户头像" /> {/* 上传组件,传入上传完成后的刷新回调 */} <Dropzone userProfileId={userProfileId} onUploadSuccess={fetchLatestImage} /> </div> ) }
可选优化(减少请求)
后端上传接口处理完S3上传逻辑后,可以直接返回该图片的访问地址:如果是公开S3桶直接返回资源URL,如果是私有桶返回预签名URL,前端拿到地址后直接更新状态即可,不需要再单独调用一次下载接口,节省带宽和请求耗时。
现有后端download方法无需改动,只要补充对应的GET接口路由即可正常使用。
内容的提问来源于stack exchange,提问作者Marquez Ludin Albarado Jaimes
相关产品推荐
相关产品推荐

