使用Skipper与Sails上传流时,写入缓冲区触发路径错误
Fixing "TypeError: path must be a string or Buffer" with skipper-better-s3
The error you're hitting comes from a common gotcha with skipper-better-s3's metadata handling: filesUploaded[0].extra.fd isn't a valid local file path or Buffer—it's actually the S3 object key (the path to your file inside the S3 bucket), which adapter.read() can't process directly. Here's how to fix this properly:
Corrected Code Example
const adapter = require('skipper-better-s3')(options); const receiver = adapter.receive({dirname: "/original"}); const upstream = req.file('file'); upstream.upload(receiver, function(err, filesUploaded){ if (err) { console.error('Upload failed:', err); return; } // Grab the S3 object key from the uploaded file's metadata const s3ObjectKey = filesUploaded[0].extra.fd; // Use the adapter's pre-configured S3 client to fetch the file adapter.s3.getObject({ Bucket: options.bucket, // Match the bucket name from your adapter initialization options Key: s3ObjectKey }, (err, s3Response) => { if (err) { console.error('Failed to read file from S3:', err); return; } // s3Response.Body is the raw image Buffer—Jimp can read this directly Jimp.read(s3Response.Body, function(err, image){ if (err) { console.error('Jimp failed to parse image:', err); return; } // Process the image, then handle the resized buffer image.resize(600, Jimp.AUTO).quality(60).getBuffer(image.getMIME(), (err, resizedImageBuffer) => { if (err) { console.error('Failed to generate resized buffer:', err); return; } // Optional: Upload the resized image back to S3 (example) adapter.s3.putObject({ Bucket: options.bucket, Key: `resized/${filesUploaded[0].filename}`, // New path for resized files Body: resizedImageBuffer, ContentType: filesUploaded[0].type }, (err) => { err ? console.error('Failed to upload resized image:', err) : console.log('Resized image saved successfully!'); }); }); }); }); });
Key Details to Know:
extra.fd= S3 object key, not local path: Skipper-better-s3 stores files directly in S3, not your server's filesystem. Thefdfield maps to the object's key in the bucket, not a local file path.- Use the built-in S3 client: The
adapter.s3property is a pre-configured AWS SDK S3 client that matches your initial adapter settings—no need to set up a new one. - Jimp works with Buffers:
s3Response.Bodyis the raw binary Buffer of your image, which Jimp accepts without extra conversion. - Add error handling everywhere: I added checks for every async step to catch issues early—this will save you hours of debugging later.
内容的提问来源于stack exchange,提问作者Eli Peters
相关产品推荐
相关产品推荐

