You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Node.js Sharp在上传至Google Cloud前调整图片大小

如何在上传至Google Cloud前用Sharp缩放图片

问题描述

已实现图片上传至Google Cloud Storage,但无法在上传前通过Sharp库对图片进行缩放,需要集成Sharp完成图片预处理后再上传。

现有上传函数代码:

const processFile = require('../middleware/upload')
const { format } = require('util')
const { Storage } = require('@google-cloud/storage')
// Instantiate a storage client with credentials
const storage = new Storage({ keyFilename: 'xxxxx.json' })
const bucket = storage.bucket('<---bucket name--->')

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

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

        // Create a new blob in the bucket and upload the file data.
        const blob = bucket.file(req.file.originalname.replace(/ /g, "_"))
        const blobStream = blob.createWriteStream({
            resumable: false,
        })

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

        blobStream.on('finish', async (data) => {
            // Create URL for directly file access via HTTP.
            const publicUrl = format(
                `https://storage.googleapis.com/${bucket.name}/${blob.name}`,
            )

            try {
                // Make the file public
                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) {
        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}`,
        })
    }
}

module.exports = {
  upload
}

现有Multer中间件代码:

const util = require("util");
const Multer = require("multer");
const maxSize = 2 * 1024 * 1024;

let processFile = Multer({
    storage: Multer.memoryStorage(),
    limits: { fileSize: maxSize },
}).single("file");

let processFileMiddleware = util.promisify(processFile);
module.exports = processFileMiddleware;

解决方案

1. 安装Sharp库

执行命令安装Sharp:

npm install sharp
# 或
yarn add sharp

2. 修改上传函数集成Sharp处理

在上传函数中引入Sharp,对req.file.buffer进行缩放处理,再将处理后的buffer传入Google Cloud的写入流。

修改后的完整上传函数代码:

const processFile = require('../middleware/upload')
const { format } = require('util')
const { Storage } = require('@google-cloud/storage')
const sharp = require('sharp') // 引入Sharp库
// Instantiate a storage client with credentials
const storage = new Storage({ keyFilename: 'xxxxx.json' })
const bucket = storage.bucket('<---bucket name--->')

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

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

        // 用Sharp处理图片:缩放至宽800px,高度按比例自适应
        let processedBuffer;
        try {
            processedBuffer = await sharp(req.file.buffer)
                .resize({ width: 800 }) // 可根据需求调整尺寸,比如height: 600,或设置fit/position等参数
                .toBuffer(); // 将处理后的图片转为buffer
        } catch (sharpErr) {
            return res.status(500).send({
                message: `Failed to process image: ${sharpErr.message}`
            });
        }

        // Create a new blob in the bucket and upload the file data.
        const blob = bucket.file(req.file.originalname.replace(/ /g, "_"))
        const blobStream = blob.createWriteStream({
            resumable: false,
            contentType: req.file.mimetype // 保持原文件的MIME类型
        })

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

        blobStream.on('finish', async (data) => {
            // Create URL for directly file access via HTTP.
            const publicUrl = format(
                `https://storage.googleapis.com/${bucket.name}/${blob.name}`,
            )

            try {
                // Make the file public - 修正为操作当前blob对象,避免文件名空格问题
                await blob.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 processed file successfully: ' + req.file.originalname,
                url: publicUrl,
            })
        })

        // 传入处理后的buffer
        blobStream.end(processedBuffer)
    } catch (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}`,
        })
    }
}

module.exports = {
  upload
}

关键调整说明

  • 引入sharp库并添加图片处理逻辑,使用resize方法设置缩放规则,可根据需求调整参数(比如固定高度、裁剪模式等)。
  • 捕获Sharp处理过程中的错误,避免上传流程崩溃。
  • 修正makePublic的目标文件:直接使用blob对象的方法,避免原文件名含空格导致的操作错误。
  • 在创建写入流时指定contentType,保证上传后的文件MIME类型正确。

可选扩展

  • 支持多种缩放规则:比如设置resize({ width: 800, height: 600, fit: 'inside' })确保图片不超出指定尺寸;或使用fit: 'cover'进行裁剪。
  • 转换图片格式:添加.jpeg({ quality: 80 })将图片转为JPEG并设置质量。
  • 批量处理:修改Multer中间件为.array("files"),循环处理每个上传的文件。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:50:25