从 phone 上传文件时,Firebase 存储(网络)无法正常工作
Firebase Storage (web) not working when files are uploaded from phone
我正在使用 Firebase 创建一个网站。用户应该能够上传和更新他们的个人资料图片,只要它小于 10mb,并且是 .jpg、.png 或 .gif 文件。
应该发生什么:
- 用户上传了一张有效的图片
- 在 Firebase 存储中创建或更新引用
/users/{uid}/profileImage
- 使用
getDownloadURL()
方法获取图像的 URL,并将其作为文本存储在 Firestore 中,在用户的个人资料信息下
- 使用 URL 作为头像的
src
。
当我尝试在我的计算机上执行此操作时 (Windows 10),它运行良好。但是,当我尝试在 phone (iPhone 8; iOS 14.7.1) 上执行此操作时,它不起作用。从 phone 上传的图像到达 /users/{uid}/profileImage
,但随后由于权限问题无法正确获取 downloadURL
,即使用户已在 phone 上进行身份验证浏览器,按照规则要求。
以下是 (1) 获取文件和 (2) 更新用户个人资料图片的代码:
// Grab dp img and store it in file var
let file = {}
const chooseFile = (e) => {
// Get the file from local machine
file = e.target.files[0]
console.log(file )
}
// Store dp in storage as file, and db as link
const updateDp = (currentUser) => {
// Check if new dp has been added/exists.
if ("name" in file) {
// Check if uploaded file is an image
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/gif") {
alert("You can only upload .jpeg, .jpg, .png and .gif under 10mb")
return
}
// Check image file size
if (file.size/1024/1024>10) {
alert("The image size must be under 10mb")
return
}
// Create storage ref & put the file in it
storage
.ref("users/" + currentUser.uid + "/profileImage")
.put(file)
.then(() => {
// success => get download link, put it in DB, update dp img src
storage
.ref("users/" + currentUser.uid + "/profileImage")
.getDownloadURL()
.then(imgURL => {
db
.collection("users")
.doc(currentUser.uid)
.set({
dp_URL: imgURL,
dp_URL_last_modified: file.lastModifiedDate
}, {
merge: true
})
document.querySelector("#nav_dp").src = imgURL;
})
console.log("success")
}).catch(() => {
console.log(error.message)
})
} else {
console.log("Empty/no file")
}
}
以下是我的 Firebase 存储规则:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{uid}/{profileImage} {
allow read: if request.auth!=null;
allow write: if request.auth!=null && request.auth.uid == uid;
}
}
}
安全规则和代码对我来说看起来不错,除了 console.log("success")
会在您获得下载 URL 之前记录为 getDownloadURL()
returns Promise。尝试将您的函数更改为异步函数,如下所示:
// Store dp in storage as file, and db as link
const updateDp = async (currentUser) => {
// ^^^^^
// Check if new dp has been added/exists.
if ("name" in file) {
try {
// Check if uploaded file is an image
if (
file.type !== "image/jpeg" &&
file.type !== "image/png" &&
file.type !== "image/gif"
) {
alert("You can only upload .jpeg, .jpg, .png and .gif under 10mb");
return;
}
// Check image file size
if (file.size / 1024 / 1024 > 10) {
alert("The image size must be under 10mb");
return;
}
// Create storage ref & put the file in it
const userPicRef = storage.ref(
"users/" + currentUser.uid + "/profileImage"
);
await userPicRef.put(file);
console.log("Image uploaded")
// success => get download link, put it in DB, update dp img src
const imgURL = await UserPicRef.getDownloadURL();
console.log(`Image URL: ${imgURL}`)
await db.collection("users").doc(currentUser.uid).set(
{
dp_URL: imgURL,
dp_URL_last_modified: file.lastModifiedDate,
},
{
merge: true,
}
);
console.log("Document Added")
document.querySelector("#nav_dp").src = imgURL;
} catch (error) {
console.log(error);
}
} else {
console.log("Empty/no file");
}
};
回答我自己的问题。
原来,我使用的是 file.lastModifiedDate
,这是一种贬值的方法。它适用于 Android 上的 Google Chrome 应用程序 运行,但不适用于 iOS。
为了修复它,我改用了 file.lastModified
。
我正在使用 Firebase 创建一个网站。用户应该能够上传和更新他们的个人资料图片,只要它小于 10mb,并且是 .jpg、.png 或 .gif 文件。
应该发生什么:
- 用户上传了一张有效的图片
- 在 Firebase 存储中创建或更新引用
/users/{uid}/profileImage
- 使用
getDownloadURL()
方法获取图像的 URL,并将其作为文本存储在 Firestore 中,在用户的个人资料信息下 - 使用 URL 作为头像的
src
。
当我尝试在我的计算机上执行此操作时 (Windows 10),它运行良好。但是,当我尝试在 phone (iPhone 8; iOS 14.7.1) 上执行此操作时,它不起作用。从 phone 上传的图像到达 /users/{uid}/profileImage
,但随后由于权限问题无法正确获取 downloadURL
,即使用户已在 phone 上进行身份验证浏览器,按照规则要求。
以下是 (1) 获取文件和 (2) 更新用户个人资料图片的代码:
// Grab dp img and store it in file var
let file = {}
const chooseFile = (e) => {
// Get the file from local machine
file = e.target.files[0]
console.log(file )
}
// Store dp in storage as file, and db as link
const updateDp = (currentUser) => {
// Check if new dp has been added/exists.
if ("name" in file) {
// Check if uploaded file is an image
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/gif") {
alert("You can only upload .jpeg, .jpg, .png and .gif under 10mb")
return
}
// Check image file size
if (file.size/1024/1024>10) {
alert("The image size must be under 10mb")
return
}
// Create storage ref & put the file in it
storage
.ref("users/" + currentUser.uid + "/profileImage")
.put(file)
.then(() => {
// success => get download link, put it in DB, update dp img src
storage
.ref("users/" + currentUser.uid + "/profileImage")
.getDownloadURL()
.then(imgURL => {
db
.collection("users")
.doc(currentUser.uid)
.set({
dp_URL: imgURL,
dp_URL_last_modified: file.lastModifiedDate
}, {
merge: true
})
document.querySelector("#nav_dp").src = imgURL;
})
console.log("success")
}).catch(() => {
console.log(error.message)
})
} else {
console.log("Empty/no file")
}
}
以下是我的 Firebase 存储规则:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{uid}/{profileImage} {
allow read: if request.auth!=null;
allow write: if request.auth!=null && request.auth.uid == uid;
}
}
}
安全规则和代码对我来说看起来不错,除了 console.log("success")
会在您获得下载 URL 之前记录为 getDownloadURL()
returns Promise。尝试将您的函数更改为异步函数,如下所示:
// Store dp in storage as file, and db as link
const updateDp = async (currentUser) => {
// ^^^^^
// Check if new dp has been added/exists.
if ("name" in file) {
try {
// Check if uploaded file is an image
if (
file.type !== "image/jpeg" &&
file.type !== "image/png" &&
file.type !== "image/gif"
) {
alert("You can only upload .jpeg, .jpg, .png and .gif under 10mb");
return;
}
// Check image file size
if (file.size / 1024 / 1024 > 10) {
alert("The image size must be under 10mb");
return;
}
// Create storage ref & put the file in it
const userPicRef = storage.ref(
"users/" + currentUser.uid + "/profileImage"
);
await userPicRef.put(file);
console.log("Image uploaded")
// success => get download link, put it in DB, update dp img src
const imgURL = await UserPicRef.getDownloadURL();
console.log(`Image URL: ${imgURL}`)
await db.collection("users").doc(currentUser.uid).set(
{
dp_URL: imgURL,
dp_URL_last_modified: file.lastModifiedDate,
},
{
merge: true,
}
);
console.log("Document Added")
document.querySelector("#nav_dp").src = imgURL;
} catch (error) {
console.log(error);
}
} else {
console.log("Empty/no file");
}
};
回答我自己的问题。
原来,我使用的是 file.lastModifiedDate
,这是一种贬值的方法。它适用于 Android 上的 Google Chrome 应用程序 运行,但不适用于 iOS。
为了修复它,我改用了 file.lastModified
。