如何从 Firebase 存储中删除 Vue.js 组件图像?
Posted
技术标签:
【中文标题】如何从 Firebase 存储中删除 Vue.js 组件图像?【英文标题】:How to delete Vue.js component image from Firebase storage? 【发布时间】:2019-12-15 03:53:59 【问题描述】:我正在构建一个 Vue.js 组件,该组件可以在 Firebase 上上传和删除图像。到目前为止,我的组件可以将图像上传到数据库和存储。图像只能从数据库中删除,但仍保留在存储中。为了解决这个问题,我尝试使用.then()
promise 设置deleteImg()
函数来定位存储中的图像以进行删除。文档中的示例 ('https://firebase.google.com/docs/storage/web/delete-files') 设置为针对硬编码图像。如何设置删除功能以删除删除按钮所针对的特定图像?这是我的删除功能:
deleteImg(img)
db.collection("images").doc(img).delete()
.then(() =>
var storageRef = firebase.storage().ref();
var desertRef = storageRef.child('images/Desert.jpg');
desertRef.delete().then(function()
console.log('Document successfully deleted')
).catch(function(error)
console.log(error)
);
)
.then(() =>
this.getImages()
)
这是整个组件:
<template>
<div id="app">
<v-app-bar color="indigo" dark fixed app>
<v-toolbar-title>Vue Firebase Image Upload</v-toolbar-title>
</v-app-bar>
<v-app id="inspire">
<v-content>
<v-container fluid>
<v-layout align-center justify-center>
<v-flex xs12 sm8 md4>
<img :src="imageUrl" v-if="imageUrl" />
<v-text-field label="Select Image" @click="pickFile" v-model="imageName"></v-text-field>
<input type="file" style="display: none" ref="image" accept="image/*" @change="onFilePicked"/>
<v-btn color="primary" @click="upload">UPLOAD</v-btn>
</v-flex>
</v-layout>
<br />
<v-layout align-center justify-center>
<v-flex xs12 sm8 md4>
<div v-for="img in imgUrls" :key="img.id">
<br />
<img :src="img.downloadUrl" />
<v-btn @click="deleteImg(img.id)">x</v-btn>
</div>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
</div>
</template>
<script>
import firebase from 'firebase'
import db from "./main";
export default
name: "App",
data()
return
photo: null,
photo_url: null,
dialog: false,
imageName: "",
imageUrl: "",
imageFile: "",
imgUrls: []
;
,
created()
this.getImages();
,
methods:
getImages: function()
db.collection("images")
.get()
.then(snap =>
const array = [];
snap.forEach(doc =>
const data = doc.data()
array.push(
id: doc.id,
...data
);
);
this.imgUrls = array;
);
this.imageName = ""
this.imageFile = ""
this.imageUrl = ""
,
pickFile()
this.$refs.image.click();
,
onFilePicked(e)
const files = e.target.files;
if (files[0] !== undefined)
this.imageName = files[0].name;
if (this.imageName.lastIndexOf(".") <= 0)
return;
const fr = new FileReader();
fr.readAsDataURL(files[0]);
fr.addEventListener("load", () =>
this.imageUrl = fr.result;
this.imageFile = files[0]; // this is an image file that can be sent to server...
);
else
this.imageName = "";
this.imageFile = "";
this.imageUrl = "";
,
upload: function()
var storageRef = firebase.storage().ref();
var mountainsRef = storageRef.child(`images/$this.imageName`);
mountainsRef.put(this.imageFile).then(snapshot =>
snapshot.ref.getDownloadURL().then(downloadURL =>
this.imageUrl = downloadURL;
const bucketName = "xxx-xxxx-xxxxx.xxxxxxx.xxx";
const filePath = this.imageName;
db.collection("images").add(
downloadURL,
downloadUrl:
`https://firebasestorage.googleapis.com/v0/b/$bucketName/o/images` +
"%2F" +
`$encodeURIComponent(filePath)?alt=media`,
originalName: this.imageName,
timestamp: Date.now()
);
this.getImages();
);
);
,
deleteImg(img)
db.collection("images").doc(img).delete()
.then(() =>
var storageRef = firebase.storage().ref();
var desertRef = storageRef.child('images/Desert.jpg');
desertRef.delete().then(function()
console.log('Document successfully deleted')
).catch(function(error)
console.log(error)
);
)
.then(() =>
this.getImages()
)
,
components:
;
</script>
<style>
#app
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
</style>
更新的删除功能
async deleteImg(img)
let imgDBRef = await db.collection("images").doc(img).get()
let imgFileName = imgDBRef.exists ? imgDBRef.data().originalName : null;
let storageRef = firebase.storage().ref();
let desertRef = storageRef.child('images/' + imgFileName);
desertRef.delete()
db.collection("images").doc(img).delete()
this.getImages()
【问题讨论】:
【参考方案1】:这是最终答案:
async deleteImg(img)
let imgDBRef = await db.collection("images").doc(img).get()
let imgFileName = imgDBRef.exists ? imgDBRef.data().originalName : null;
let storageRef = firebase.storage().ref();
let desertRef = storageRef.child('images/' + imgFileName);
await desertRef.delete()
await db.collection("images").doc(img).delete()
await this.getImages()
【讨论】:
这里的许多其他答案都具有误导性或已弃用。这个解决方案效果很好!谢谢,@JS_is_awesome18 :)【参考方案2】:要从存储中删除图片,您需要知道该图片在 Cloud Storage 存储分区中的路径。如果你只有图片的下载地址,你可以通过firebase.storage().refFromUrl(...)
获取引用,然后在结果中调用delete()
。
【讨论】:
您好弗兰克,感谢您的反馈。我了解如何在上传功能的上下文中使用存储路径,但不了解删除功能。你能稍微扩展一下吗?我试图将您所说的应用于我的deleteImg()
函数,但无济于事。在答案底部查看我的更新功能..
您的deleteImg
代码乍一看还不错。该代码有什么问题?当您在调试器中单步执行时,哪一行没有按照您的预期执行?
我收到两个错误。先说Error in v-on handler: "[object Object]
。其次是 FirebaseStorageError(见上文)
不能从存储中删除。删除数据库中的文件路径,以及屏幕上的图像。但是图像仍然保留在存储中。我也想删除它。
那么,在调试器中单步调试代码,path 指向什么desertRef
?那确实是要删除的图像吗?如果是这样,它是在该行之后进入then()
还是进入catch()
块?【参考方案3】:
我认为您应该尝试将图像文件名保存到数据库,以便能够将其映射到存储项。
从这里添加imageName
:
storageRef.child(`images/$this.imageName`);
到db.collection("images").add(..)
函数参数对象:
db.collection("images").add(
downloadURL,
originalName: this.imageName,
);
然后在您的deleteImg
函数中从db.collection("images").doc(img)
文档数据中获取originalName
,如下所示:
const imgDBRef = db.collection("images").doc(img).get();
const imgFileName = imgDBRef.exists ? imgDBRef.data().originalName : null;
//... here should be your checks for image name nullable state etc.
const storageRef = firebase.storage().ref();
const desertRef = storageRef.child('images/' + imgFileName);
最好将文件名存储为哈希,而不是真实名称。
【讨论】:
感谢您的回复!我合并了您的答案,但控制台不断返回空值。我将在答案中更新我的删除功能,向您展示我是如何添加它的。有关如何解决此问题的任何建议? 您确定您通过db.collection("images").doc(img)
代码获得了对图像的引用吗?尝试通过console.log
进行检查,然后如果引用不为空,请尝试使用originalName
获取文档值。
我设置了 console.log(imgFileName) 以查看基于 let imgFileName = imgDBRef.exists ? imgDBRef.data().originalName : null;
分配给该 imgFileName 的内容。控制台不断返回 null,这意味着 imgFileName 永远不会真正获得 originalName
。是否有另一种方法可以建议您分配对 imgfileName 的引用而不是使用三元语句?
尝试将let imgFileName = imgDBRef.exists ? imgDBRef.data().originalName : null;
替换为let imgData = imgDBRef.exists ? imgDBRef.data() : null;
,然后检查哪些字段在dataconsole.log(imgData);
我们应该检查,imgData确实包含您在上传时设置的一些字段。
再次感谢。 console.log 仍然为此返回 null。以上是关于如何从 Firebase 存储中删除 Vue.js 组件图像?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Vue Web 应用程序中的 Firebase 存储下载文件?
如何删除用户点击按钮? - Firebase - Vue.js