Nodejs应用程序无法通过Google云存储桶正确验证?

bsxbgnwa  于 2023-02-21  发布在  Node.js
关注(0)|答案(1)|浏览(116)

构建应用用户档案照片组件。我设置了一个没有公共访问权限的Google Cloud存储桶,使用细粒度ACL,以及一个具有存储管理员角色的服务帐户。我下载了JSON密钥,放在根目录中package.json旁边,并在我的文件上传/下载控制器中引用:

const processFile = require("../middleware/upload");
const { format } = require("util");
const { Storage } = require("@google-cloud/storage");
const storage = new Storage({ keyFilename: "my-service-account.json" });
const bucket = storage.bucket("my-gcp-storage-bucket");

const upload = async (req, res) => {
    try {
        await processFile(req, res);

        if (!req.file) {
            return res.status(400).send({ message: "Please upload a file!" });
        }

        const blob = bucket.file(req.file.originalname);
        const blobStream = blob.createWriteStream({
            resumable: false,
        });

        blobStream.on("error", (err) => {
            res.status(500).send({ message: err.message });
        });

        blobStream.on("finish", async (data) => {
            const publicUrl = format(
                `https://storage.googleapis.com/${bucket.name}/${blob.name}`
            );

            try {
                await bucket.file(req.file.originalname).makePublic();
            } catch {
                return res.status(500).send({
                    message:
                        `Uploaded the file successfully: ${req.file.originalname}, but public access is denied!`,
                    url: publicUrl,
                });
            }

            res.status(200).send({
                message: "Uploaded the file successfully: " + req.file.originalname,
                url: publicUrl,
            });
        });

        blobStream.end(req.file.buffer);
    } catch (err) {
        console.log(err);

        if (err.code == "LIMIT_FILE_SIZE") {
            return res.status(500).send({
                message: "File size cannot be larger than 2MB!",
            });
        }

        res.status(500).send({
            message: `Could not upload the file: ${req.file.originalname}. ${err}`,
        });
    }
};

const getListFiles = async (req, res) => {
    try {
        const [files] = await bucket.getFiles();
        let fileInfos = [];

        files.forEach((file) => {
            fileInfos.push({
                name: file.name,
                url: file.metadata.mediaLink,
            });
        });

        res.status(200).send(fileInfos);
    } catch (err) {
        console.log(err);

        res.status(500).send({
            message: "Unable to read list of files!",
        });
    }
};

const download = async (req, res) => {
    try {
        const [metaData] = await bucket.file(req.params.name).getMetadata();
        res.redirect(metaData.mediaLink);

    } catch (err) {
        res.status(500).send({
            message: "Could not download the file. " + err,
        });
    }
};

module.exports = {
    upload,
    getListFiles,
    download,
};

我可以上传到我的bucket和list文件,但无法下载或在React前端查看图像预览。尝试使用下载API时,我收到以下消息:

  • 匿名呼叫者没有对Google云存储对象的storage.objects.get访问权限。对资源的权限“storage.objects.get "被拒绝(或者资源可能不存在)。*

具体来说,这些是不起作用的:

const getListFiles = async (req, res) => {
    try {
        const [files] = await bucket.getFiles();
        let fileInfos = [];

        files.forEach((file) => {
            fileInfos.push({
                name: file.name,
                url: file.metadata.mediaLink,
            });
        });

        res.status(200).send(fileInfos);
    } catch (err) {
        console.log(err);

        res.status(500).send({
            message: "Unable to read list of files!",
        });
    }
};

const download = async (req, res) => {
    try {
        const [metaData] = await bucket.file(req.params.name).getMetadata();
        res.redirect(metaData.mediaLink);

    } catch (err) {
        res.status(500).send({
            message: "Could not download the file. " + err,
        });
    }
};

我不知道这里出了什么问题,因为我可以上传和列出文件-只是不能下载。有什么想法吗?

mrphzbgm

mrphzbgm1#

确保服务帐户具有下载文件所需的权限。有关详细信息,请参阅此文档1和文档2。
经过身份验证的用户必须具有storage.objects.get IAM权限才能使用此方法。若要返回对象ACL,经过身份验证的用户还必须具有storage.objects.getIamPolicy权限。
同时初始化gcloud环境gcloud init,然后通过运行gcloud auth application-default login设置应用程序默认凭据。

相关问题