Firebase中下载并重传图片遇存储异常,求解决方法
问题描述
我的图片存储在Firebase Storage中,对应的URL存在Realtime Database里,数据结构如下:
Type1 ----Time1 --------elements of type1 ----Time2 --------elements of type2 Type2 ....
我需要允许用户修改元素的时间,所以要把元素从一个Time分支移到另一个分支。目前的实现逻辑是在新分支创建新元素,再删除旧元素,但同步图片的时候出了问题。
我试过用Uri.parse()解析Realtime Database里存的URL,也试过用StorageReference.getDownloadUrl()获取Uri,但都报同样的错误:
could not locate file for uploading:https://firebasestorage.googleapis.com/v0/b/re... E/StorageException: StorageException has occurred. An unknown error occurred, please check the HTTP result code and inner exception for server response. Code: -13000 HttpResult: 0
手动点击错误里的链接能正常显示图片,但程序就是找不到文件。我的代码如下:
storageReference = FirebaseStorage.getInstance().getReference().child("images/Anime/General/Test1"); storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { storageReference = FirebaseStorage.getInstance().getReference().child("images/Anime/Future/Test1"); storageReference.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { ... } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { } }); } });
错误出现在storageReference.putFile(uri)这一行。
问题原因与解决方案
问题原因
putFile()方法的设计是用来上传本地文件/设备内的Uri(比如content://开头的本地资源地址),而你传入的是Firebase Storage生成的HTTPS下载链接,这种网络Uri不在putFile()的支持范围内,所以程序会提示找不到文件。
解决方案
最推荐的方式是直接在Firebase Storage内部复制文件,不需要下载再上传,既高效又避免网络问题:
方法1:使用StorageReference的copyTo()方法
直接获取旧文件的Storage引用,调用copyTo()复制到新路径,完成后更新Realtime Database里的URL,最后删除旧文件即可。示例代码:
// 获取旧文件的Storage引用 StorageReference oldRef = FirebaseStorage.getInstance().getReference().child("images/Anime/General/Test1"); // 定义新文件的Storage引用 StorageReference newRef = FirebaseStorage.getInstance().getReference().child("images/Anime/Future/Test1"); // 执行复制操作 oldRef.copyTo(newRef).addOnSuccessListener(new OnSuccessListener<StorageMetadata>() { @Override public void onSuccess(StorageMetadata storageMetadata) { // 复制成功后,获取新文件的下载URL newRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri newUri) { // 更新Realtime Database中对应元素的图片URL // ... 这里写更新数据库的逻辑 // 最后删除旧文件(可选,根据业务需求决定) oldRef.delete().addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void unused) { // 旧文件删除成功 } }); } }); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // 复制失败,处理错误 } });
方法2:下载后再上传(不推荐)
如果必须用下载再上传的方式,需要先把网络图片下载到本地存储,得到本地文件的Uri,再调用putFile()上传。这种方式会消耗额外的带宽和时间,仅在特殊场景下使用。
内容的提问来源于stack exchange,提问作者C-Gian
相关产品推荐
相关产品推荐

