简体   繁体   English

Firebase Cloud功能用于在firestore创建时调整图像大小

[英]Firebase Cloud Function to resize image on firestore create

I am trying to achieve following. 我正在努力实现以下目标。 But, I have no idea as I am a beginner to firebase. 但是,我不知道因为我是firebase的初学者。

  1. User is trying to upload a post with image 用户正在尝试上传包含图片的帖子
  2. Image is selected from web browser 从Web浏览器中选择图像
  3. When user clicks save button, I am uploading the selected image to firbase storage and getting the download URL. 当用户单击“保存”按钮时,我将所选图像上载到firbase存储并获取下载URL。
  4. Inserting the post data with download url to firestore database. 将带有下载URL的帖子数据插入到firestore数据库。

Till this, I have completed. 直到这个,我已经完成了。 Now, I need to resize the uploaded image. 现在,我需要调整上传的图像大小。

For that, I am trying to use Cloud Functions, whenever a new entry is added to firestore database, I am calling a Cloud fountion, which can access the download URL of the image, using this download URL, I need to resize image. 为此,我正在尝试使用云功能,每当新条目添加到firestore数据库时,我都会调用Cloud fountion,它可以访问图像的下载URL,使用此下载URL,我需要调整图像大小。 Please help. 请帮忙。

Please let me know, if there are having any better approach to achieve this. 如果有更好的方法来实现这一点,请告诉我。 (I know there should be :P ) (我知道应该有:P)

Edit 1 编辑1

Thank you Frank for your reply. 谢谢弗兰克的回复。

I have the below cloud function, which will be called for every post is inserted. 我有下面的云功能,将为每个帖子插入调用。 I am getting the download URL of the image from the eventSnapshot. 我从eventSnapshot获取图像的下载URL。 I need to resize the image in that location. 我需要调整该位置的图像大小。 Please help. 请帮忙。

exports.resizeImage = functions.firestore
.document('posts/{postId}')
.onCreate(event => {
        var eventSnapshot = event.data.data();
        //In this eventSnapshot I am getting the document, and I can get the download URL from the document
});

I have analyzed the example to create thumbnail, but for that, I need the 我已经分析了创建缩略图的示例,但为此,我需要
storage object, and it will be called only when the storage object is changed. 存储对象,只有在更改存储对象时才会调用它。 But, I need to do the thumbnail creation when the onWrite called in firestore. 但是,当在firestore中调用onWrite时,我需要创建缩略图。

 exports.generateThumbnail = functions.storage.object().onChange((event) => {
  // File and directory paths.
  const filePath = event.data.name;
});

Please let me know, how to do the image resize operation, by detecting the onWrite in firestore and using downLoadURL. 请通过检测firestore中的onWrite并使用downLoadURL告诉我如何进行图像大小调整操作。

Rather than take the URL from Cloud Firestore, you can have Cloud Storage trigger the Cloud Function to resize the image. 您可以让Cloud Storage触发云功能来调整图像大小,而不是从Cloud Firestore获取URL。 There is a great example of how to do this, on GitHub. 在GitHub上有一个很好的例子。

Firebase SDK for Cloud Functions Quickstart - Cloud Storage trigger 适用于云功能的Firebase SDK快速入门 - 云存储触发器

I, too, have created a document in firestore that I'm using as the backend to a website. 我也在firestore中创建了一个文档,我将其用作网站的后端。 I, too, would like to resize the image (to fit on a card) and write the URL back to firestore. 我也想调整图像大小(适合卡片)并将URL写回firestore。 I found a solution that uses a different pattern from the standard examples that are triggered by uploading the image to storage. 我发现了一种解决方案,它使用与将图像上传到存储所触发的标准示例不同的模式。

Basically, I upload the image to storage and then write the URL into Firestore within my app page. 基本上,我将图像上传到存储,然后在我的应用页面中将URL写入Firestore。 I then trigger the function with Firestore's onCreate() trigger. 然后我使用Firestore的onCreate()触发器触发该函数。

The function grabs 'image_name' from firestore and uses that to get the file reference in storage. 该函数从firestore中获取“image_name”并使用它来获取存储中的文件引用。 Next, it follows the patterns of the generate-thumbnail firebase example. 接下来,它遵循generate-thumbnail firebase示例的模式。

The trick was then grabbing the signedUrl and writing it back to firestore in img_src. 然后诀窍是抓住signedUrl并将其写回img_src中的firestore。

In case anyone else finds this useful: 如果其他人发现这有用:

const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')({keyFilename: 'service-key.json'});
const spawn = require('child-process-promise').spawn;
const path = require('path');
const os = require('os');
const fs = require('fs');

exports.createCard = functions.firestore
  .document('work_cards/{cardID}')
  .onCreate((snap, context) => {
    const newCardData = snap.data()
    const bucket = gcs.bucket('your-project-id.appspot.com')
    const file = bucket.file(newCardData.image_name)
    const tempFilePath = path.join(os.tmpdir(), file.name);
    const thumbFileName = `thumb_${file.name}`;
    const thumbFilePath = bucket.file(thumbFileName)
    const contentType = file.contentType;
    const metadata = {
      contentType: contentType
    };

    return bucket.file(file.name).download({
        destination: tempFilePath,
      })
      .then(() => {
        return spawn('convert', [tempFilePath, '-thumbnail', '250x250', tempFilePath]);
      })
      .then(() => {
        return bucket.upload(tempFilePath, {
          destination: thumbFilePath,
          metadata: metadata,
        })
      })
      .then(() => {
        return thumbFilePath.getSignedUrl({
        action: 'read',
        expires: '03-09-2491'
        })
      })
      .then(signedUrls => {
        const img_src = signedUrls[0]
        return snap.ref.set({img_src}, {merge: true});
      })
      .then(() => {
        bucket.file(file.name).delete()
        fs.unlinkSync(tempFilePath)
        return
      })
    });

I needed to achieve this too, but for me, using the Cloud Storage trigger wasn't a suitable solution as I didn't want to resize everything. 我也需要实现这一点,但对我来说,使用云存储触发器不是一个合适的解决方案,因为我不想调整所有内容。

My scenario was that a user would upload a number of images, but they picked one as the thumbnail. 我的情况是用户会上传一些图像,但他们选择了一个作为缩略图。 I modified Birch's code as a callable function, where the file reference data was passed to it 我修改了Birch的代码作为可调用函数,其中文件引用数据被传递给它

exports.generateThumbnail = functions.https.onCall((data, context) => {
  const file = bucket.file(`/designs/${context.auth.uid}/${data.design}/${data.image}`)
  const tempFilePath = path.join(os.tmpdir(), `${data.image}`);
  const thumbFileName = `thumb_${data.image}`;
  const thumbFilePath = bucket.file(`/designs/${context.auth.uid}/${data.design}/${thumbFileName}`);

  return bucket.file(file.name).download({
       destination: tempFilePath,
     })
     .then(() => {
       return spawn('convert', [tempFilePath, '-trim','-resize', '190', tempFilePath]);
     })
     .then(() => {
       return bucket.upload(tempFilePath, {
         destination: thumbFilePath,
       })
     })
     .then(() => {
       fs.unlinkSync(tempFilePath)
       return
     })
})

I made it by generating and setting thumbnail when our user create or update firestore object. 当我们的用户创建或更新firestore对象时,我通过生成和设置缩略图来实现。

resizeImage.ts resizeImage.ts

import * as admin from "firebase-admin";
const mkdirp = require("mkdirp-promise");
import { spawn } from "child-process-promise";
import * as path from "path";
import * as os from "os";
import * as fs from "fs";

export default async function resizeImage(
    filePath: string,
    size: string
): Promise<string> {
    // File and directory paths.
    const fileDir = path.dirname(filePath);
    const fileName = path.basename(filePath);
    const thumbFilePath = path.normalize(
        path.join(fileDir, `thumb_${size}_${fileName}`)
    );
    const tempLocalFile = path.join(os.tmpdir(), filePath);
    const tempLocalDir = path.dirname(tempLocalFile);
    const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);

    // Cloud Storage files.
    const bucket = admin.storage().bucket();
    const file = bucket.file(filePath);
    const thumbFile = bucket.file(thumbFilePath);
    const metadata = {
        contentType: null
        // To enable Client-side caching you can set the Cache-Control headers here. Uncomment below.
        // 'Cache-Control': 'public,max-age=3600',
    };
    await file.getMetadata().then(data => {
        if (data && data[0] && data[0]["contentType"]) {
            metadata["contentType"] = data[0]["contentType"];
        }
    });

    // Create the temp directory where the storage file will be downloaded.
    await mkdirp(tempLocalDir);
    // Download file from bucket.
    await file.download({ destination: tempLocalFile });
    console.log("The file has been downloaded to", tempLocalFile);
    // Generate a thumbnail using ImageMagick.
    await spawn(
        "convert",
        [
            tempLocalFile,
            "-auto-orient",
            "-thumbnail",
            `${size}>`,
            tempLocalThumbFile
        ],
        { capture: ["stdout", "stderr"] }
    );
    console.log("Thumbnail created at", tempLocalThumbFile);
    // Uploading the Thumbnail.
    await bucket.upload(tempLocalThumbFile, {
        destination: thumbFilePath,
        metadata: metadata
    });
    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);
    return thumbFile
        .getSignedUrl({
            action: "read",
            expires: "03-01-2500"
        })
        .then((urls: string[]) => urls[0]);
}

resizeAvatar.ts resizeAvatar.ts

const functions = require("firebase-functions");
import { Change } from "firebase-functions";
import resizeImage from "./resizeImage";

async function resizeAvatar(snapshot: FirebaseFirestore.DocumentSnapshot) {
    const data = snapshot.data();
    const filePath = data && data.avatarPath;
    if (!data || !filePath || data.avatarUrlSmall) {
        return; // No avatar or already resized
    }
    const url = await resizeImage(filePath, "200x200");
    await snapshot.ref.set({ avatarUrlSmall: url }, { merge: true });
}

exports.resizeAvatarOnCreate = functions.firestore
    .document("users/{userID}")
    .onCreate(async (snapshot: FirebaseFirestore.DocumentSnapshot) => {
        await resizeAvatar(snapshot);
    });

exports.resizeAvatarOnUpdate = functions.firestore
    .document("users/{userID}")
    .onUpdate(async (change: Change<FirebaseFirestore.DocumentSnapshot>) => {
        await resizeAvatar(change.after);
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Firestore Cloud Function:出现“ReferenceError:firebase 未定义” - Firestore Cloud Function: Getting “ReferenceError: firebase is not defined” Firebase Cloud Function CreateUser 上 Firestore 中的增量计数器 - Firebase Cloud Function increment counter in Firestore on CreateUser Firebase Cloud Function with Firestore 返回“Deadline Exceeded” - Firebase Cloud Function with Firestore returning "Deadline Exceeded" Firebase 云功能不更新 Firestore 数据库中的数据 - Firebase Cloud function not updating data in Firestore database 尝试初始化 Cloud Firestore 时,firebase.firestore() 不是函数 - firebase.firestore() is not a function when trying to initialize Cloud Firestore 将图像存储在Firebase存储中并在Firebase Cloud Firestore(Beta)中保存元数据 - Store image in Firebase Storage and save metadata in Firebase Cloud Firestore (Beta) Cloud Function:裁剪图像 &gt; 调整为多种尺寸 - Cloud Function: Crop image > Resize to multiple sizes Firebase Cloud Function:Cloud Firestore 查询无效,即使数据在 Cloud Firestore 中 - Firebase Cloud Function : Cloud Firestore query invalid eventhough data is in Cloud Firestore Firebase云功能/ Firestore - Firebase Cloud Functions / Firestore Firebase Cloud Firestore noSQL - Firebase Cloud Firestore noSQL
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM