英文:
How uploaded file on Firebase storage then store the url inside firestore with vue 3 (composition API)
问题
我是您的中文翻译,这是您要翻译的代码部分:
im new to firebase and vue 3 and i have prob dealing with upload to storage, i am uploading the file (image) on firebase and want to store it to firestore with all other data from inputs, i was able to save all data from form but cant with the file url, im using this fucntion :
<input @change="uploadTaskPromise" class="file-input" type="file" name="file">
import { getStorage, ref as stRef, uploadBytesResumable, getDownloadURL } from "firebase/storage";
const uploadTaskPromise = (e) => {
const file = e.target.files[0];
const storage = getStorage();
const metadata = {
contentType: 'image/jpeg'
};
const storageRef = stRef(storage, 'products/' + file.name);
const uploadTask = uploadBytesResumable(storageRef, file, metadata);
uploadTask.on('state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case 'paused':
console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
},
(error) => {
switch (error.code) {
case 'storage/unauthorized':
break;
case 'storage/canceled':
break;
// ...
case 'storage/unknown':
break;
}
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
resolve({ imgUrl: downloadURL });
});
});
}
英文:
im new to firebase and vue 3 and i have prob dealing with upload to storage, i am uploading the file (image) on firebase and want to store it to firestore with all other data from inputs, i was able to save all data from form but cant with the file url, im using this fucntion :
<input @change="uploadTaskPromise" class="file-input" type="file" name="file">
import { getStorage, ref as stRef, uploadBytesResumable, getDownloadURL } from "firebase/storage";
const uploadTaskPromise = (e) => {
const file = e.target.files[0];
const storage = getStorage();
const metadata = {
contentType: 'image/jpeg'
};
const storageRef = stRef(storage, 'products/' + file.name);
const uploadTask = uploadBytesResumable(storageRef, file, metadata);
uploadTask.on('state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case 'paused':
console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
},
(error) => {
switch (error.code) {
case 'storage/unauthorized':
break;
case 'storage/canceled':
break;
// ...
case 'storage/unknown':
break;
}
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
resolve({ imgUrl: downloadURL });
});
});
}
答案1
得分: 1
以下是您要翻译的内容:
首先,我制作了一个简单的表单...
<template>
<form action="#" @submit.prevent>
<div>
<label for="title">产品标题</label>
<input v-model="title" type="text" id="title" placeholder="标题" />
</div>
<div>
<label for="price">产品价格</label>
<input v-model="price" type="number" id="price" min="0" placeholder="0.00" />
</div>
<div>
<label for="file">产品照片</label>
<input @change="handleFileChange" type="file" id="file" />
</div>
<button @click="submitForm">发送</button>
</form>
</template>
...并且与脚本连接:
<script>
// 这些变量在config.js中设置
import { storage, productsCollectionRef } from '../firebase/config'
// 这是来自Firebase的上传文件所需的函数
import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage'
// 这个用于在数据库(Firestore)中创建文档
import { addDoc } from 'firebase/firestore'
export default {
// 子组件,在主要的App.vue中导入
name: 'vue-upload',
data() {
return {
title: null,
price: 0,
file: null
}
},
methods: {
handleFileChange(e) {
// 当选择文件时,更新数据()中的属性
this.file = e.target.files[0]
},
createProduct(data) {
// 传递到集合和数据的引用
addDoc(productsCollectionRef, data)
},
uploadFile(file) {
// 从File对象中获取名称和类型属性
const { name, type } = file
// 在Firebase中创建文件引用
const storageRef = ref(storage, 'images/' + name)
// 上传文件(this.file)到Firebase并附加元数据
const uploadTask = uploadBytesResumable(storageRef, this.file, {
contentType: type
})
uploadTask.on(
'state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
console.log('上传进度:' + progress + '%')
},
(error) => {
console.log(error)
},
() => {
// 上传成功。获取URL...
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
// ...创建要写入的数据...
const data = {
title: this.title,
price: this.price,
url: downloadURL
}
// ...并调用一个写入文档到Firestore的函数
this.createProduct(data)
})
}
)
},
submitForm() {
// 简单的快速验证
if (this.title && this.price && this.file) {
this.uploadFile(this.file)
return
}
alert('表单无效')
}
}
}
</script>
您可能注意到了import { storage, productsCollectionRef } from '../firebase/config'
这一行。
这只是另一个JavaScript文件,我在其中传递了Firebase的配置:
./firebase/config.js
import { initializeApp } from 'firebase/app'
import { getStorage } from 'firebase/storage'
import { getFirestore, collection } from 'firebase/firestore'
const firebaseConfig = {
apiKey: 'XXXXX',
authDomain: 'XXXXX',
projectId: 'XXXXX',
storageBucket: 'XXXXX',
messagingSenderId: 'XXXXX',
appId: 'XXXXX'
}
// 初始化Firebase
const app = initializeApp(firebaseConfig)
const storage = getStorage(app)
const db = getFirestore(app)
// 在我的Firestore数据库中,我创建了一个'products'集合 [截图][1]
const productsCollectionRef = collection(db, 'products')
// 我们需要导出这些设置好的变量以供在其他文件中使用
export { storage, productsCollectionRef }
英文:
First of all - i've made a simple form ...
<template>
<form action="#" @submit.prevent>
<div>
<label for="title">Product title</label>
<input v-model="title" type="text" id="title" placeholder="Title" />
</div>
<div>
<label for="price">Product price</label>
<input v-model="price" type="number" id="price" min="0" placeholder="0.00" />
</div>
<div>
<label for="file">Product photo</label>
<input @change="handleFileChange" type="file" id="file" />
</div>
<button @click="submitForm">Send</button>
</form>
</template>
... and connected it with script
<script>
// this variables setup-ed in config.js
import { storage, productsCollectionRef } from '../firebase/config'
// this function from firebase. need to upload file
import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage'
// this one for creating document in database (firestore)
import { addDoc } from 'firebase/firestore'
export default {
// child component, imported in main App.vue
name: 'vue-upload',
data() {
return {
title: null,
price: 0,
file: null
}
},
methods: {
handleFileChange(e) {
// when file selected - update property in data()
this.file = e.target.files[0]
},
createProduct(data) {
// pass a reference to collection and data
addDoc(productsCollectionRef, data)
},
uploadFile(file) {
// getting name & type properties from File object
const { name, type } = file
// create a reference to file in firebase
const storageRef = ref(storage, 'images/' + name)
// upload file (this.file) to firebase and append metadata
const uploadTask = uploadBytesResumable(storageRef, this.file, {
contentType: type
})
uploadTask.on(
'state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
console.log('Upload is ' + progress + '% done')
},
(error) => {
console.log(error)
},
() => {
// successful upload. get url ...
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
// ... make a data to write ...
const data = {
title: this.title,
price: this.price,
url: downloadURL
}
// ... and call a fn that writes a document to a firestore
this.createProduct(data)
})
}
)
},
submitForm() {
// just quick & simple validation
if (this.title && this.price && this.file) {
this.uploadFile(this.file)
return
}
alert('Form invalid')
}
}
}
</script>
You may notice a import { storage, productsCollectionRef } from '../firebase/config'
line.
It's just another one js-file, where i pass configuration for firebase:
./firebase/config.js
import { initializeApp } from 'firebase/app'
import { getStorage } from 'firebase/storage'
import { getFirestore, collection } from 'firebase/firestore'
const firebaseConfig = {
apiKey: 'XXXXX',
authDomain: 'XXXXX',
projectId: 'XXXXX',
storageBucket: 'XXXXX',
messagingSenderId: 'XXXXX',
appId: 'XXXXX'
}
// Initialize Firebase
const app = initializeApp(firebaseConfig)
const storage = getStorage(app)
const db = getFirestore(app)
// i've made a 'products' collection in my firestore database [screenshot][1]
const productsCollectionRef = collection(db, 'products')
// we need export this setuped variables for use in another file
export { storage, productsCollectionRef }
答案2
得分: 0
@bahyllam我没有足够的声望添加评论。在你之前的代码(4月10日5:05)中,你在`this.files`中有一个数组,但是你的`uploadFile(file)`函数接受单个`file`作为参数。所以在这个函数内部,你需要为整个数组做一个循环,分别为每个`file`调用所有的代码(为每个文件获取`name`和`type`,创建`storageRef`和`uploadTask`。但只进行一次写操作:
handleFileChange(e) {
if (e.target.files) {
for (const file of e.target.files) {
this.files.push(file)
}
}
}
uploadFile() {
const urls = []
const promises = []
this.files.forEach((file) => {
// getting name & type properties from each File object
const { name, type } = file
// create a reference to each file in firebase
const storageRef = ref(storage, 'images/' + name)
// upload each file to firebase and append metadata
const uploadTask = uploadBytesResumable(storageRef, file, {
contentType: type
})
// create task with promises. this will help us to expect the result correctly
const promise = new Promise((resolve, reject) => {
uploadTask.on(
'state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
console.log('Upload is ' + progress + '% done')
},
(error) => {
console.log(error)
reject(error)
},
async () => {
// wait for URL from getDownloadURL
const url = await getDownloadURL(uploadTask.snapshot.ref)
urls.push(url)
resolve(url)
}
)
})
// add task to "waitlist"
promises.push(promise)
})
// when all "waitlist" resolve ...
Promise.all(promises).then(() => {
// ... make a data to write ...
const data = {
title: this.title,
price: this.price,
// url: [Array]
url: urls
}
// ... and call a fn that writes a document to a firestore
this.createProduct(data)
})
}
<details>
<summary>英文:</summary>
@bahyllam i don't have enough reputation to add a comment.
in your previous code (Apr 10 at 5:05), you have an array in `this.files`, but your `uploadFile(file)` function takes a single `file` as an argument.
So inside this function you need to make a loop for the whole array and call all the code for each `file` separately (get a `name` & `type` for each file, make `storageRef` and `uploadTask`. BUT only once make a write operation:
handleFileChange(e) {
if (e.target.files) {
for (const file of e.target.files) {
this.files.push(file)
}
}
}
uploadFile() {
const urls = []
const promises = []
this.files.forEach((file) => {
// getting name & type properties from each File object
const { name, type } = file
// create a reference to each file in firebase
const storageRef = ref(storage, 'images/' + name)
// upload each file to firebase and append metadata
const uploadTask = uploadBytesResumable(storageRef, file, {
contentType: type
})
// create task with promises. this will help us to expect the result correctly
const promise = new Promise((resolve, reject) => {
uploadTask.on(
'state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
console.log('Upload is ' + progress + '% done')
},
(error) => {
console.log(error)
reject(error)
},
async () => {
// wait for URL from getDownloadURL
const url = await getDownloadURL(uploadTask.snapshot.ref)
urls.push(url)
resolve(url)
}
)
})
// add task to "waitlist"
promises.push(promise)
})
// when all "waitlist" resolve ...
Promise.all(promises).then(() => {
// ... make a data to write ...
const data = {
title: this.title,
price: this.price,
// url: [Array]
url: urls
}
// ... and call a fn that writes a document to a firestore
this.createProduct(data)
})
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论