如何将 Firebase 上传图片的图片下载 URL 转换为 base64

Posted

技术标签:

【中文标题】如何将 Firebase 上传图片的图片下载 URL 转换为 base64【英文标题】:How to convert image downloadURL for Firebase upload image to base64 【发布时间】:2019-12-26 22:55:43 【问题描述】:

我正在尝试在 Vue.js Firebase 应用程序中实现图像上传器组件。我将上传器设置为首先使用 .put() 将图像放入 Firebase 存储中。然后使用.getDownloadURL() 检索downloadURL,然后将其保存到数据库中以便在整个应用程序中呈现:this.imageUrl = downloadURL。上传几张图片后,我注意到存储在数据库中的一些图片的 downloadURL 显示为 base64 字符串,而其他图片的 downloadURL 显示为以https://firebasestorage.googleapis.com/... 开头的常规 URL。我希望 downloadURL 在数据库中始终如一地出现。哪种格式更适合存储在数据库中?如何设置下面的代码以一致地解释其中一种?我的代码如下。谢谢!

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

完整的组件

<template>
  <div class="sign-up">
    <v-container fluid fill-height>
     <v-layout align-center justify-center>
       <v-flex xs12 sm8 md4>
         <v-card class="elevation-8">
           <v-toolbar dark color="primary">
             <v-toolbar-title>Let's create a new account!</v-toolbar-title>
           </v-toolbar>
           <v-card-text>
             <v-form>
               <v-text-field prepend-icon="person" v-model="email" name="email" label="Email" type="text"></v-text-field>
               <v-text-field prepend-icon="lock" v-model="password" name="password" label="Password" id="password" type="password"></v-text-field>
               <v-text-field prepend-icon="lock" v-model="name" name="name" label="Name" id="name" type="text"></v-text-field>

               <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-flex>
               </v-layout>

             </v-form>
           </v-card-text>
           <v-card-actions>
             <v-container>
               <v-btn @click="signUp" color="info">Sign Up</v-btn>
             </v-container>
           </v-card-actions>
         </v-card>
         <v-card-text>Return to <router-link to="/login"><strong>login</strong></router-link>.</v-card-text>
       </v-flex>
     </v-layout>
   </v-container>
  </div>
</template>
<script>
import slugify from 'slugify'
import firebase from 'firebase'
import db from '@/firebase/init'
export default 
  name: 'signUp',
  data () 
    return 
      email: '',
      password: '',
      name: '',
      slug: null,
      imageName: null,
      imageUrl: '',
      downloadUrl: '',
      imageFile: null
    
  ,
  methods: 
    signUp () 
      if (this.name && this.email && this.password) 
        this.slug = slugify(this.name, 
          replacement: '-',
          remove: /[$*_+~,()'"!\-:@]/g,
          lower: true
        )
        // UPLOAD
        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
          )
        )
        // end UPLOAD
        let ref = db.collection('users').doc(this.slug)
        ref.get().then(doc => 
          if (doc.exists) 
            this.feedback = 'This alias already exists'
           else 
            firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
              .then(cred => 
                ref.set(
                  name: this.name,
                  email: this.email,
                  user_id: cred.user.uid,
                  imageUrl: this.imageUrl,
                  downloadUrl: this.downloadUrl
                )
              ).then(() => 
                this.$router.push( name: 'Dashboard' )
              )
              .catch(err => 
                this.feedback = err.message
              )
            this.feedback = 'This alias is free to use'
          
        )
       else 
        this.feedback = 'You must enter all fields'
      
    ,
    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]
        )
       else 
        this.imageName = ''
        this.imageFile = ''
        this.imageUrl = ''
      
    
  

</script>

【问题讨论】:

下载 url 应始终显示为常规 https url。你是怎么保存的。有哪些显示不同的 URL 示例? 感谢您的回复。数据库中一个图像的 imageUrl 读取为“data:image/jpeg;base64,/>”,而另一个读取为“firebasestorage.googleapis.com/v0/b...” 查看上面的更新组件。我之前发布的代码 sn-p 是一个更大的注册表单组件的一部分。上传和存储使用.set() 方法执行的配置文件图像。提交表单后图像渲染得很好,但我想知道为什么有些图像以 base64 格式保存在数据库中,而另一些则使用常规 https url 保存。 【参考方案1】:

“存储在数据库中的某些图像的下载 URL 显示为 base64 字符串,而其他图像的下载 URL 显示为常规 URL”的原因是因为您在上传部分之前将 imageUrl 设置为您的用户准备好了..所以你最终保存了this.imageUrl,它最初设置为FileReader.result

相反,您应该等到从firebase.storage 获得正确的downloadURL,并且只有then 设置您的用户imageUrl

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

       let ref = db.collection('users').doc(this.slug)
        ref.get().then(doc => 
          if (doc.exists) 
            this.feedback = 'This alias already exists'
           else 
            firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
              .then(cred => 
                ref.set(
                  name: this.name,
                  email: this.email,
                  user_id: cred.user.uid,
                  imageUrl: this.imageUrl,
                  downloadUrl: this.downloadUrl
                )
              ).then(() => 
                this.$router.push( name: 'Dashboard' )
              )
              .catch(err => 
                this.feedback = err.message
              )
            this.feedback = 'This alias is free to use'
          
        )
    )
)

【讨论】:

谢谢@maxim。问题...您是否也愿意看看这个关于 Vue.js 和 Firestore 的新问题? ***.com/questions/58249933/…

以上是关于如何将 Firebase 上传图片的图片下载 URL 转换为 base64的主要内容,如果未能解决你的问题,请参考以下文章

将图片从 URL 上传到 Firebase 存储

firebase 存储 cors 奇怪的行为

我应该将图片上传到 Cloud Firestore 还是 Firebase Storage?

将图片上传到 Firebase 存储并显示为个人资料图片

将图片上传到 Firebase

使用 Google Firebase 同时上传多张图片