使用Fetch API获取Firebase Storage图片返回空Blob问题求助
问题分析与解决方案
首先,你遇到的空Blob问题,核心原因是**mode: 'no-cors'的限制**。当使用no-cors模式时,浏览器会返回一个「不透明响应(opaque response)」,这种响应的内容是无法被JavaScript读取的——这就是为什么你得到Blob {size: 0, type: ""}的原因。
另外,虽然你的图片URL带了下载token,理论上可以绕过Firebase的认证规则,但no-cors模式直接阻断了响应内容的读取,这才是关键问题。
下面给你几个可行的解决方案:
方案1:移除mode: 'no-cors',并确保请求能通过认证
因为你的Firebase Storage规则要求request.auth != null,如果你的前端已经有用户登录(通过Firebase Auth),可以直接移除no-cors模式,同时让Fetch请求带上认证信息。修改后的代码如下:
getImage = async () => { const url = "https://firebasestorage.googleapis.com/v0/b/alpha-c790f.appspot.com/o/images%2Frivers.jpg?alt=media&token=6a96d672-23c1-425f-bdca-47f6d73608f0"; try { // 如果已经通过Firebase Auth登录,获取当前用户的ID Token const user = firebase.auth().currentUser; const idToken = await user.getIdToken(); const response = await fetch(url, { headers: { Authorization: `Bearer ${idToken}` } }); if (!response.ok) { throw new Error(`请求失败:${response.status}`); } const res = await response.blob(); console.log(res); const objectURL = URL.createObjectURL(res); const myImage = new Image(); myImage.src = objectURL; // 这里可以监听myImage的load事件,隐藏加载动画 myImage.onload = () => { console.log("图片加载完成"); // 执行你的加载动画隐藏逻辑 }; } catch(err) { console.log(err); } }
方案2:利用图片的onload事件实现加载动画(无需Fetch)
其实你不需要用Fetch来实现「加载完成前显示动画」的需求,直接用<img>标签的onload事件就可以做到,这样更简单,还能避免CORS相关的问题:
<!-- 页面中的HTML --> <div class="loading-spinner" id="loadingSpinner">加载中...</div> <img id="targetImage" style="display: none;" />
// JavaScript代码 const loadingSpinner = document.getElementById('loadingSpinner'); const targetImage = document.getElementById('targetImage'); targetImage.onload = () => { // 图片加载完成,隐藏加载动画,显示图片 loadingSpinner.style.display = 'none'; targetImage.style.display = 'block'; }; targetImage.onerror = () => { loadingSpinner.textContent = '图片加载失败'; }; // 设置图片地址 targetImage.src = "https://firebasestorage.googleapis.com/v0/b/alpha-c790f.appspot.com/o/images%2Frivers.jpg?alt=media&token=6a96d672-23c1-425f-bdca-47f6d73608f0";
这种方式不需要处理Fetch的CORS问题,直接利用浏览器原生的图片加载事件,就能完美实现加载动画的需求。
方案3:调整Firebase Storage规则(不推荐,除非公开访问)
如果你的图片是可以公开访问的,可以修改Storage规则为:
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read: if true; allow write: if request.auth != null; } } }
修改后,你可以移除mode: 'no-cors',直接用Fetch获取Blob,同时不需要携带认证信息。但注意,这样所有用户都能访问你的图片,安全性要根据你的业务需求判断。
内容的提问来源于stack exchange,提问作者Paramveer Kahlon
相关产品推荐
相关产品推荐

