图片未使用 Multer 上传到 Google 云存储?

Image Not Uploading to Google Cloud Storage with Multer?

编辑:找出问题,解决方案如下。

我正在使用 multer 和 multer google 存储尝试将图像文件上传到我的 Google Cloud Bucket,但由于某些原因文件没有保存到 Google Cloud Bucket,我无法记录任何错误,不确定我在这里做错了什么。 (已尝试遵循几个不同的教程、阅读文档、检查其他 SO 问题等。仍然没有解决方案)。

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const passport = require('passport');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const multer = require('multer');
const path = require('path');
const multerGoogleStorage = require('multer-google-storage');


const { Storage } = require('@google-cloud/storage'); 

const gc = new Storage({
    projectId: '{projectIdRedacted}',
    keyFilename: path.join(__dirname, '../{keyFileNameRedacted.json}')
});

gc.getBuckets().then(x => console.log(x));

// This is showing that I've successfully paired to the Google Cloud bucket. 

const bucket = gc.bucket('{redactedBucketNameHere}');

const fileFilter = (req, file, cb) => {
    // Reject a file 
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
        cb(null, true);
    } else {
        cb(null, false);
    }
};


var uploadHandler = multer({ 
    storage: multer.memoryStorage(), 
    limits: {
        fileSize: 1024 * 1024 * 1
    },
    fileFilter: fileFilter
});

// Testing GCP Bucket Image Upload
// @route   POST image-upload
// @desc    Add image
// @access  Private
router.post('/image-upload', uploadHandler.single('UploadBox'), passport.authenticate('jwt', {
    session: false
}), (req, res, next) => {

    // This is showing the req.file is being passed through
    console.log(req.file);

    const blob = bucket.file(req.file.originalname);

    const blobStream = blob.createWriteStream({
        metadata: {
            contentType: req.file.mimetype
        },
        resumable: false
    });

    // The err is not getting console logged even though it is not saving to the google cloud bucket properly?
    blobStream.on('error', err => {
        next(err);
        console.log(err);
        return;
    })

    // The publicUrl is not getting console.logged - presumably cause something is breaking before this and it won't save it
    blobStream.on('finish', () => {
        // the public url can be used to directly access the file via HTTP
        const publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`;
        console.log(publicUrl);

        // Make the image public to the web (since we'll be displaying it in the browser)
        blob.makePublic().then(() => {
            res.status(200).send(`Success!\n Image uploaded to ${publicUrl}`);
        })
    })
});

@google-cloud/storage 的文档是:https://www.npmjs.com/package/@google-cloud/storage multer google 存储的文档是:https://www.npmjs.com/package/multer-google-storage Google 的云存储使用指南文档为:https://cloud.google.com/appengine/docs/flexible/nodejs/using-cloud-storage

任何提示和帮助将不胜感激。

编辑:我找到了解决方案。我不得不将 uploadHandler 和 fileFilter 上移到 const { storage} 导入之上。然后在路线内,我必须在 blobStream.on('finish') 之后添加 "blobStream.end();"。这样做之后就解决了。我已经编辑了下面的工作代码。

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const passport = require('passport');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const multer = require('multer');
const path = require('path');
const multerGoogleStorage = require('multer-google-storage');


const fileFilter = (req, file, cb) => {
    // Reject a file 
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
        cb(null, true);
    } else {
        cb(null, false);
    }
};

var uploadHandler = multer({ 
    storage: multer.memoryStorage(), 
    limits: {
        fileSize: 1024 * 1024 * 1
    },
    fileFilter: fileFilter
});


const { Storage } = require('@google-cloud/storage'); 

const gc = new Storage({
    projectId: '{projectIdRedacted}',
    keyFilename: path.join(__dirname, '../{keyFileNameRedacted.json}')
});

gc.getBuckets().then(x => console.log(x));

const bucket = gc.bucket('{bucketNameRedacted}');

// Testing GCP Bucket Image Upload
// @route   POST image-upload
// @desc    Add image
// @access  Private
router.post('/image-upload', uploadHandler.single('UploadBox'), passport.authenticate('jwt', {
    session: false
}), (req, res, next) => {

    // This is showing the req.file is being passed through
    console.log(req.file);

    const blob = bucket.file(req.file.originalname);

    const blobStream = blob.createWriteStream({
        metadata: {
            contentType: req.file.mimetype
        },
        resumable: false
    });

    // The err is not getting console logged even though it is not saving to the google cloud bucket properly?
    blobStream.on('error', err => {
        next(err);
        console.log(err);
        return;
    })

    // The publicUrl is not getting console.logged - presumably cause something is breaking before this and it won't save it
    blobStream.on('finish', () => {
        // the public url can be used to directly access the file via HTTP
        const publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`;
        console.log(publicUrl);

        // Make the image public to the web (since we'll be displaying it in the browser)
        blob.makePublic().then(() => {
            res.status(200).send(`Success!\n Image uploaded to ${publicUrl}`);
        })
    })

    blobStream.end();
});

顺便说一下,您并不真的需要 multer-google-storage 包。

请评论您在点击用于此上传的路线时收到的响应错误消息。

我想出了解决办法。我不得不将 uploadHandler 和 fileFilter 上移到 const { storage} 导入之上。然后在路线内,我必须在 blobStream.on('finish') 之后添加 "blobStream.end();"。这样做之后就解决了。我已经编辑了下面的工作代码。

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const passport = require('passport');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const multer = require('multer');
const path = require('path');
const multerGoogleStorage = require('multer-google-storage');


const fileFilter = (req, file, cb) => {
    // Reject a file 
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
        cb(null, true);
    } else {
        cb(null, false);
    }
};

var uploadHandler = multer({ 
    storage: multer.memoryStorage(), 
    limits: {
        fileSize: 1024 * 1024 * 1
    },
    fileFilter: fileFilter
});


const { Storage } = require('@google-cloud/storage'); 

const gc = new Storage({
    projectId: '{projectIdRedacted}',
    keyFilename: path.join(__dirname, '../{keyFileNameRedacted.json}')
});

gc.getBuckets().then(x => console.log(x));

const bucket = gc.bucket('{bucketNameRedacted}');

// Testing GCP Bucket Image Upload
// @route   POST image-upload
// @desc    Add image
// @access  Private
router.post('/image-upload', uploadHandler.single('UploadBox'), passport.authenticate('jwt', {
    session: false
}), (req, res, next) => {

    // This is showing the req.file is being passed through
    console.log(req.file);

    const blob = bucket.file(req.file.originalname);

    const blobStream = blob.createWriteStream({
        metadata: {
            contentType: req.file.mimetype
        },
        resumable: false
    });

    // The err is not getting console logged even though it is not saving to the google cloud bucket properly?
    blobStream.on('error', err => {
        next(err);
        console.log(err);


   return;
    })

// The publicUrl is not getting console.logged - presumably cause something is breaking before this and it won't save it
blobStream.on('finish', () => {
    // the public url can be used to directly access the file via HTTP
    const publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`;
    console.log(publicUrl);

    // Make the image public to the web (since we'll be displaying it in the browser)
    blob.makePublic().then(() => {
        res.status(200).send(`Success!\n Image uploaded to ${publicUrl}`);
    })
})

blobStream.end();
});