背景:我正在将Firebase Cloud Functions,新的Firestore数据库和存储桶与Android客户端一起使用。
我要完成的任务: 当用户将图片上传到存储桶时,我想使用云功能获取到存储桶中图像位置的文件路径/链接,并将此字符串作为新文档存储在“图片”下的新集合下。当前已在Firestore中登录用户的文档。
这样,我可以看到每个用户直接在Firestore中上传的图像,这使得将特定用户的图像下拉到Android客户端变得更加容易。
到目前为止我已经完成的事情: 1.用户首次登录时,它将在新的Firestore数据库中创建一个用户文档。 2.登录的用户可以将图像上传到存储桶。 3.使用Firebase Cloud Functions,我设法获得了存储位置的文件路径/链接,如下所示:
/**
* When a user selects a profile picture on their device during onboarding,
* the image is sent to Firebase Storage from a function running on their device.
* The cloud function below returns the file path of the newly uploaded image.
*/
exports.getImageStorageLocationWhenUploaded = functions.storage.object().onFinalize((object) => {
const filePath = object.name; // File path in the bucket.
const contentType = object.contentType; // File content type.
// Exit if this is triggered on a file that is not an image.
if (!contentType.startsWith('image/')) {
console.log('This is not an image.');
return null;
}
console.log(filePath);
});
问题:如何使用Cloud Functions将当前登录的用户的上传图像文件路径/链接作为新文档存储在Firestore数据库中此登录用户的文档下? / p>
答案 0 :(得分:3)
当前,使用Cloud Storage触发器,您无权访问经过身份验证的用户信息。要解决此问题,您必须执行一些操作,例如将uid嵌入文件的路径中,或将uid作为元数据添加到文件上传中。
答案 1 :(得分:0)
我有一个类似的问题,我想将用户上传的图像与他/她的 uid 相关联。我找到了一个优雅的解决方案,它不一定需要在文件路径中插入 uid,甚至不需要将其作为元数据添加到文件上传中。实际上,uid 通过标准的 idToken 编码安全地传输到数据库。此示例采用了生成缩略图云函数示例(找到 here)的修改版本,我相信问题的作者正在使用/暗指。以下是步骤:
客户端:
const generateThumbnail = firebase.functions().httpsCallable('generateThumbnail');
const getImageUrl = (file) => {
firebase.auth().currentUser.getIdToken(true)
.then((idToken) => generateThumbnail({
idToken,
imgName: file.name,
contentType: file.type
}))
.then((data) => {
// Here you can save your image url to the app store, etc.
// An example of a store action:
// setImageUrl(data.data.url);
})
.catch((error) => {
console.log(error);
})
}
on
方法的第三个参数实现。将上面的触发器函数作为第三个参数包含在此处。// Function triggered on file import status change from the <input /> tag
const createThumbnail = (e) => {
e.persist();
let file = e.target.files[0];
// If you are using a non default storage bucket use this
// let storage = firebase.app().storage('gs://your_non_default_storage_bucket');
// If you are using the default storage bucket use this
let storage = firebase.storage();
// You can add the uid in the image file path store location but this is optional
let storageRef = storage.ref(`${uid}/thumbnail/${file.name}`);
storageRef.put(file).on('state_changed', (snapshot) => {}, (error) => {
console.log('Something went wrong! ', error);
}, getImageUrl(file));
}
服务器端:
// Import your admin object with the initialized app credentials
const mkdirp = require('mkdirp');
const spawn = require('child-process-promise').spawn;
const path = require('path');
const os = require('os');
const fs = require('fs');
// Max height and width of the thumbnail in pixels.
const THUMB_MAX_HEIGHT = 25;
const THUMB_MAX_WIDTH = 125;
// Thumbnail prefix added to file names.
const THUMB_PREFIX = 'thumb_';
async function generateThumbnail(data) {
// Get the user uid from IdToken
const { idToken, imgName, contentType } = data;
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
const uid = decodedIdToken.uid;
// File and directory paths.
const filePath = `${uid}/thumbnail/${imgName}`;
const fileDir = path.dirname(filePath);
const fileName = path.basename(filePath);
const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}`));
const tempLocalFile = path.join(os.tmpdir(), filePath);
const tempLocalDir = path.dirname(tempLocalFile);
const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);
// Exit if this is triggered on a file that is not an image.
if (!contentType.startsWith('image/')) {
return console.log('This is not an image.');
}
// Exit if the image is already a thumbnail.
if (fileName.startsWith(THUMB_PREFIX)) {
return console.log('Already a Thumbnail.');
}
// Cloud Storage files.
const bucket = initDb.storage().bucket('your_bucket_if_non_default');
const originalFile = bucket.file(filePath);
// Create the temp directory where the storage file will be downloaded.
// But first check to see if it does not already exists
if (!fs.existsSync(tempLocalDir)) await mkdirp(tempLocalDir);
// Download original image file from bucket.
await originalFile.download({ destination: tempLocalFile });
console.log('The file has been downloaded to', tempLocalFile);
// Delete the original image file as it is not needed any more
await originalFile.delete();
console.log('Delete the original file as it is not needed any more');
// Generate a thumbnail using ImageMagick.
await spawn('convert', [ tempLocalFile, '-thumbnail',
`${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`, tempLocalThumbFile],
{ capture: ['stdout', 'stderr'] }
);
console.log('Thumbnail created at', tempLocalThumbFile);
// Uploading the Thumbnail.
const url = await uploadLocalFileToStorage(tempLocalThumbFile, thumbFilePath,
contentType);
console.log('Thumbnail uploaded to Storage at', thumbFilePath);
// Once the image has been uploaded delete the local files to free up disk space.
fs.unlinkSync(tempLocalFile);
fs.unlinkSync(tempLocalThumbFile);
// Delete the uid folder from temp/pdf folder
fs.rmdirSync(tempLocalDir);
await admin.database().ref(`users/${uid}/uploaded_images`).update({ logoUrl: url[0] });
return { url: url[0] };
}
// Upload local file to storage
exports.uploadLocalFileToStorage = async (tempFilePath, storageFilePath,
contentType, customBucket = false) => {
let bucket = initDb.storage().bucket();
if (customBucket) bucket = initDb.storage().bucket(customBucket);
const file = bucket.file(storageFilePath);
try {
// Check if file already exists; if it does delete it
const exists = await file.exists();
if (exists[0]) await file.delete();
// Upload local file to the bucket
await bucket.upload(tempFilePath, {
destination: storageFilePath,
metadata: { cacheControl: 'public, max-age=31536000', contentType }
});
const currentDate = new Date();
const timeStamp = currentDate.getTime();
const newDate = new Date(timeStamp + 600000);
const result = await file.getSignedUrl({
action: 'read',
expires: newDate
});
return result;
} catch (e) {
throw new Error("uploadLocalFileToStorage failed: " + e);
}
};
答案 2 :(得分:0)
if (firebase.auth().currentUser !== null)
console.log("user id: " + firebase.auth().currentUser.uid);
获取用户用户 ID 的简单方法。