如何使用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
相关产品推荐
相关产品推荐

