如何使用 reactjs 将图像上传到 Firebase web v9
How to upload images to Firebase web v9 using reactjs
我在将图像上传到 firebase 但使用网络版本 9 时遇到问题。
我正在关注他正在构建 Facebook 克隆的其中一个平台上的教程。我被困在 firebase 上传图像和文件的这一部分......
我检查了 firebase 的文档,并试图弄清楚应该更改,但我做不到。
我想要的是将 firebase 代码从旧版本转换为最新的 Web V9。
这是我的代码,但在以前的版本中:
import { useSession } from 'next-auth/client';
import { useRef, useState } from 'react';
import { db, storage } from '../firebase';
import firebase from 'firebase';
function InputBox() {
const [session] = useSession();
const inputRef = useRef(null);
const filepickerRef = useRef(null);
const[imageToPost, setImageToPost] = useState(null);
const sendPost = (e) => {
e.preventDefault();
if (!inputRef.current.value) return;
db.collection('posts').add({
message: inputRef.current.value,
name: session.user.name,
email: session.user.email,
image: session.user.image,
timestamp: firebase.firestore.FieldValue.serverTimestamp()
}).then(doc => {
if (imageToPost) {
const uploadTask = storage.ref(`posts/${doc.id}`).putString(imageToPost, 'data_url')
removeImage();
uploadTask.on('state_change', null, error => console.error(error),
() => {
//When the upload completes
storage.ref(`posts`).child(doc.id).getDownloadURL().then(url => {
db.collection('posts').doc(doc.id).set({
postImage: url
},
{ merge: true}
);
});
});
}
});
inputRef.current.value = "";
};
const addImageToPost = (e) => {
const reader = new FileReader();
if (e.target.files[0]) {
reader.readAsDataURL(e.target.files[0]);
}
reader.onload = (readerEvent) => {
setImageToPost(readerEvent.target.result);
};
};
const removeImage = () => {
setImageToPost(null);
};
return (here is my jsx)
其实一切都在documentation.
里有详细说明
替换uploadTask
定义
const uploadTask = storage.ref(`posts/${doc.id}`).putString(imageToPost, 'data_url')
做
import { getStorage, ref, uploadString, getDownloadURL } from "firebase/storage";
const storage = getStorage();
const storageRef = ref(storage, `posts/${doc.id}`);
const message = 'This is my message.';
const uploadTask = uploadString(storageRef, imageToPost, 'data_url');
并替换上传监控块,做
import { doc, setDoc } from "firebase/firestore";
uploadTask.on('state_changed',
null
(error) => {
// ...
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setDoc(doc(db, "posts", doc.id), { postImage: url }, { merge: true});
});
}
);
请注意 UploadTask
object behaves like a Promise,并在上传完成时解析其快照数据,因此如果您只对完整事件感兴趣,也可以 uploadTask.then()
。
如果您的 firebaseConfig 没问题,那么这应该可以!
import { setDoc, doc } from "firebase/firestore";
import { ref, uploadString, getDownloadURL, getStorage } from "firebase/storage";
if (imageToPost) {
const storage = getStorage();
const storageRef = ref(storage, `posts/${docum.id}`);
const uploadTask = uploadString(storageRef, imageToPost, 'data_url');
uploadTask.on('state_changed', null,
(error) => {
alert(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref)
.then((URL) => {
setDoc(doc(db, "posts", docum.id), { postImage:URL }, { merge: true});
});
}
)
removeImage();
};
我遇到了同样的错误,并且能够使用 async await 解决它。我知道这是一个正统的方法,但我成功了。
我使用了与 Renaud Tarnec 相同的逻辑,这就是文档示例所具有的逻辑,但我仍然知道 uploadTask 不是一个函数,很可能是一些异步问题。
请看下面我的例子,你可以很容易地适应你的。
请记住,我没有发现任何错误,但我建议您这样做。
const sendPost = async () => {
// I used uuid package to generate Ids
const id = uuid();
const storageRef = ref(storage, `posts/${id}`);
// I await the uploadTast to finish
const uploadTask = await uploadString(storageRef, cameraImage, 'data_url');
//than get the url
const url = await getDownloadURL(uploadTask.ref);
//finally add the document to the DB
await setDoc(
doc(db, 'posts', id),
{
imageUrl: url,
username: 'Apollo',
read: false,
//profilePic,
timestamp: serverTimestamp(),
},
{ merge: true }
);
navigate('/chats');
};
希望这对您或遇到同样问题的任何人有所帮助。
我猜你正在看 Sonny FB clone 卡在了新的 FB 变化中。这个版本适合我。
import { collection, addDoc, serverTimestamp, doc, setDoc } from "firebase/firestore";
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from"firebase/storage";
const sendPost = (e) => {
e.preventDefault();
if (!inputRef.current.value) return;
// Add a new document with a generated id.
addDoc(collection(db, "posts"), {
message: inputRef.current.value,
name: session.user.name,
email: session.user.email,
image: session.user.image,
timestamp: serverTimestamp(),
}).then(docum => {
if (imageToPost) {
const storage = getStorage();
const storageRef = ref(storage, `posts/${docum.id}`);
const uploadTask = uploadBytesResumable(storageRef, imageToPost, "data_url");
removeImage();
uploadTask.on('state_changed', null,
(error) => {
console.log(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref)
.then((URL) => {
setDoc(doc(db, "posts", docum.id), { postImage: URL }, { merge: true });
});
}
)
};
});
inputRef.current.value = ""
}
截至 2021 年 12 月 4 日对我有用
2022 年更新=>
import {
ref,
uploadBytesResumable,
getDownloadURL,
getStorage,
} from "firebase/storage";
const uploadPO = async (e) => {
try {
if (e.target.files && e.target.files[0]) {
let reader = new FileReader();
reader.onload = (e) => {
poImg.current = e.target.result;
};
const file = e.target.files[0];
reader.readAsDataURL(file);
setMessage("Uploading...");
const storage = getStorage();
const storageRef = ref(storage, `Erogon_Images/${file.name}`);
const uploadTask = uploadBytesResumable(storageRef, file, "data_url");
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setMessage(`Upload is ${progress}% done`);
},
(error) => {
// Handle unsuccessful uploads
throw error;
},
() => {
// Handle successful uploads on complete
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
const body = {
rfqID,
PO: downloadURL,
};
Api.post(PATH.updatePO,body).then(()=>{
setMessage("Uploaded Successfully");
}).catch(err => {
console.log(err)
})
});
}
);
}
} catch (err) {
console.log(err);
poImg.current = null;
setMessage("");
notifyError(
err?.message || "Something went wrong while uploading to storage"
);
}
};
这就是我解决问题的方法。按照上述解决方案,使用 'uploadBytesResumable' 函数意味着我无法渲染我的图像,因为它们以错误的格式返回。我改回 'uploadString' 并将我的代码编辑为如下所示:
const sendPost = async e => {
e.preventDefault();
if (!inputRef.current.value) return;
addDoc(collection(db, 'posts'), {
message: inputRef.current.value,
name: session.user.name,
email: session.user.email,
image: session.user.image,
timestamp: serverTimestamp(),
}).then(docum => {
if (imageToPost) {
const storage = getStorage();
const storageRef = ref(storage, `posts/${docum.id}`);
uploadString(storageRef, imageToPost, 'data_url').then(snapshot => {
getDownloadURL(snapshot.ref).then(URL => {
setDoc(
doc(db, 'posts', docum.id),
{ postImage: URL },
{ merge: true }
);
console.log('File available at ', URL);
});
removeImage();
});
}
});
inputRef.current.value = '';
};
我在将图像上传到 firebase 但使用网络版本 9 时遇到问题。 我正在关注他正在构建 Facebook 克隆的其中一个平台上的教程。我被困在 firebase 上传图像和文件的这一部分...... 我检查了 firebase 的文档,并试图弄清楚应该更改,但我做不到。 我想要的是将 firebase 代码从旧版本转换为最新的 Web V9。 这是我的代码,但在以前的版本中:
import { useSession } from 'next-auth/client';
import { useRef, useState } from 'react';
import { db, storage } from '../firebase';
import firebase from 'firebase';
function InputBox() {
const [session] = useSession();
const inputRef = useRef(null);
const filepickerRef = useRef(null);
const[imageToPost, setImageToPost] = useState(null);
const sendPost = (e) => {
e.preventDefault();
if (!inputRef.current.value) return;
db.collection('posts').add({
message: inputRef.current.value,
name: session.user.name,
email: session.user.email,
image: session.user.image,
timestamp: firebase.firestore.FieldValue.serverTimestamp()
}).then(doc => {
if (imageToPost) {
const uploadTask = storage.ref(`posts/${doc.id}`).putString(imageToPost, 'data_url')
removeImage();
uploadTask.on('state_change', null, error => console.error(error),
() => {
//When the upload completes
storage.ref(`posts`).child(doc.id).getDownloadURL().then(url => {
db.collection('posts').doc(doc.id).set({
postImage: url
},
{ merge: true}
);
});
});
}
});
inputRef.current.value = "";
};
const addImageToPost = (e) => {
const reader = new FileReader();
if (e.target.files[0]) {
reader.readAsDataURL(e.target.files[0]);
}
reader.onload = (readerEvent) => {
setImageToPost(readerEvent.target.result);
};
};
const removeImage = () => {
setImageToPost(null);
};
return (here is my jsx)
其实一切都在documentation.
里有详细说明替换uploadTask
定义
const uploadTask = storage.ref(`posts/${doc.id}`).putString(imageToPost, 'data_url')
做
import { getStorage, ref, uploadString, getDownloadURL } from "firebase/storage";
const storage = getStorage();
const storageRef = ref(storage, `posts/${doc.id}`);
const message = 'This is my message.';
const uploadTask = uploadString(storageRef, imageToPost, 'data_url');
并替换上传监控块,做
import { doc, setDoc } from "firebase/firestore";
uploadTask.on('state_changed',
null
(error) => {
// ...
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setDoc(doc(db, "posts", doc.id), { postImage: url }, { merge: true});
});
}
);
请注意 UploadTask
object behaves like a Promise,并在上传完成时解析其快照数据,因此如果您只对完整事件感兴趣,也可以 uploadTask.then()
。
如果您的 firebaseConfig 没问题,那么这应该可以!
import { setDoc, doc } from "firebase/firestore";
import { ref, uploadString, getDownloadURL, getStorage } from "firebase/storage";
if (imageToPost) {
const storage = getStorage();
const storageRef = ref(storage, `posts/${docum.id}`);
const uploadTask = uploadString(storageRef, imageToPost, 'data_url');
uploadTask.on('state_changed', null,
(error) => {
alert(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref)
.then((URL) => {
setDoc(doc(db, "posts", docum.id), { postImage:URL }, { merge: true});
});
}
)
removeImage();
};
我遇到了同样的错误,并且能够使用 async await 解决它。我知道这是一个正统的方法,但我成功了。
我使用了与 Renaud Tarnec 相同的逻辑,这就是文档示例所具有的逻辑,但我仍然知道 uploadTask 不是一个函数,很可能是一些异步问题。
请看下面我的例子,你可以很容易地适应你的。
请记住,我没有发现任何错误,但我建议您这样做。
const sendPost = async () => {
// I used uuid package to generate Ids
const id = uuid();
const storageRef = ref(storage, `posts/${id}`);
// I await the uploadTast to finish
const uploadTask = await uploadString(storageRef, cameraImage, 'data_url');
//than get the url
const url = await getDownloadURL(uploadTask.ref);
//finally add the document to the DB
await setDoc(
doc(db, 'posts', id),
{
imageUrl: url,
username: 'Apollo',
read: false,
//profilePic,
timestamp: serverTimestamp(),
},
{ merge: true }
);
navigate('/chats');
};
希望这对您或遇到同样问题的任何人有所帮助。
我猜你正在看 Sonny FB clone 卡在了新的 FB 变化中。这个版本适合我。
import { collection, addDoc, serverTimestamp, doc, setDoc } from "firebase/firestore";
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from"firebase/storage";
const sendPost = (e) => {
e.preventDefault();
if (!inputRef.current.value) return;
// Add a new document with a generated id.
addDoc(collection(db, "posts"), {
message: inputRef.current.value,
name: session.user.name,
email: session.user.email,
image: session.user.image,
timestamp: serverTimestamp(),
}).then(docum => {
if (imageToPost) {
const storage = getStorage();
const storageRef = ref(storage, `posts/${docum.id}`);
const uploadTask = uploadBytesResumable(storageRef, imageToPost, "data_url");
removeImage();
uploadTask.on('state_changed', null,
(error) => {
console.log(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref)
.then((URL) => {
setDoc(doc(db, "posts", docum.id), { postImage: URL }, { merge: true });
});
}
)
};
});
inputRef.current.value = ""
}
截至 2021 年 12 月 4 日对我有用
2022 年更新=>
import {
ref,
uploadBytesResumable,
getDownloadURL,
getStorage,
} from "firebase/storage";
const uploadPO = async (e) => {
try {
if (e.target.files && e.target.files[0]) {
let reader = new FileReader();
reader.onload = (e) => {
poImg.current = e.target.result;
};
const file = e.target.files[0];
reader.readAsDataURL(file);
setMessage("Uploading...");
const storage = getStorage();
const storageRef = ref(storage, `Erogon_Images/${file.name}`);
const uploadTask = uploadBytesResumable(storageRef, file, "data_url");
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setMessage(`Upload is ${progress}% done`);
},
(error) => {
// Handle unsuccessful uploads
throw error;
},
() => {
// Handle successful uploads on complete
// For instance, get the download URL: https://firebasestorage.googleapis.com/...
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
const body = {
rfqID,
PO: downloadURL,
};
Api.post(PATH.updatePO,body).then(()=>{
setMessage("Uploaded Successfully");
}).catch(err => {
console.log(err)
})
});
}
);
}
} catch (err) {
console.log(err);
poImg.current = null;
setMessage("");
notifyError(
err?.message || "Something went wrong while uploading to storage"
);
}
};
这就是我解决问题的方法。按照上述解决方案,使用 'uploadBytesResumable' 函数意味着我无法渲染我的图像,因为它们以错误的格式返回。我改回 'uploadString' 并将我的代码编辑为如下所示:
const sendPost = async e => {
e.preventDefault();
if (!inputRef.current.value) return;
addDoc(collection(db, 'posts'), {
message: inputRef.current.value,
name: session.user.name,
email: session.user.email,
image: session.user.image,
timestamp: serverTimestamp(),
}).then(docum => {
if (imageToPost) {
const storage = getStorage();
const storageRef = ref(storage, `posts/${docum.id}`);
uploadString(storageRef, imageToPost, 'data_url').then(snapshot => {
getDownloadURL(snapshot.ref).then(URL => {
setDoc(
doc(db, 'posts', docum.id),
{ postImage: URL },
{ merge: true }
);
console.log('File available at ', URL);
});
removeImage();
});
}
});
inputRef.current.value = '';
};