简体   繁体   English

如何从Firebase存储中删除Vue.js组件映像?

[英]How to delete Vue.js component image from Firebase storage?

I am building a Vue.js component that enables uploading and deleting of images on Firebase. 我正在构建一个Vue.js组件,该组件可以在Firebase上上传和删除图像。 So far, my component enables uploading images to database and storage. 到目前为止,我的组件允许将图像上传到数据库和存储。 The image can be deleted only from the database, but still remains in storage. 该图像只能从数据库中删除,但仍保留在存储中。 To resolve this, I have attempted to set up the deleteImg() function with a .then() promise to target images in storage for deleting. 为了解决这个问题,我尝试使用deleteImg() .then()承诺将deleteImg()函数设置为以存储中的图像为目标进行删除。 The example in the docs (' https://firebase.google.com/docs/storage/web/delete-files ') is setup to target a hard-coded image. docs(“ https://firebase.google.com/docs/storage/web/delete-files ”)中的示例已设置为定位硬编码的图像。 How can I set my delete function to remove specific images targeted by a delete button? 如何设置删除功能以删除删除按钮定位的特定图像? Here is my delete function: 这是我的删除功能:

    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()
      })
    }

Here is entire component: 这是整个组件:

<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" height="150" 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" height="150" />
                <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>


UPDATED DELETE FUNCTION 更新的删除功能

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()
}

I think you should try to save an image file name to the DB in order to have ability to map it to the storage item. 我认为您应该尝试将图像文件名保存到数据库中,以便能够将其映射到存储项。

Add imageName from here: 从此处添加imageName

storageRef.child(`images/${this.imageName}`);

to db.collection("images").add(..) function argument object: db.collection("images").add(..)函数参数对象:

db.collection("images").add({
            downloadURL,
            originalName: this.imageName,
          });

and then in your deleteImg function just get the originalName from db.collection("images").doc(img) document data something like this: 然后在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);

And it's better to store file names as hashes, not real names. 而且最好将文件名存储为哈希,而不是实名。

To delete an image from storage, you'll need to know the path to that image in the Cloud Storage bucket. 要从存储中删除映像,您需要知道Cloud Storage存储桶中该映像的路径。 If you only have the download URL for the image, you can get a reference with firebase.storage().refFromUrl(...) and then call delete() in the result. 如果只有图像的下载URL,则可以使用firebase.storage().refFromUrl(...)获取引用,然后在结果中调用delete()

Here is the final answer: 这是最终答案:

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()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM