Cloudflare documentation seems to be lacking in classic fetch requests to upload files to an R2 bucket. Here is my current process in the files:
The flow in this file is handling the image uploaded via multer, adding the photo to the database, and then finally uploading the photo to R2. Everything works up until the final PUT
request to cloudflare.
photoRouter.ts:
const upload = multer({
storage: multer.memoryStorage(),
limits: { fileSize: 10 * 1024 * 1024 }, // 10 MB limit
});
router.post('/', upload.single('image'), createPhoto, uploadPhoto, (req, res) => {
return res.json({ id: res.locals.imageId, response: res.locals.response });
});
photoController.ts:
export const uploadPhoto: RequestHandler = async (req, res, next: NextFunction) => {
// throw an error if req.file is undefined
if (!req.file) {
return next({
log: 'Image not provided',
status: 404,
});
}
const { buffer, mimetype } = req.file;
const contentType = mimetype || 'image/jpeg';
const fileType = getFileType(mimetype);
const imageId = res.locals.imageId; // Make sure imageId is set correctly
// Construct URL for Cloudflare R2
const url = `https://${R2.accountId}.r2.cloudflarestorage.com/${R2.bucketName}/${imageId}.${fileType}`;
const headers = {
'Content-Type': contentType,
Authorization: `Bearer ${R2.accessKey}`, // Ensure correct authorization header
};
try {
const response = await fetch(url, {
method: 'PUT', // Use PUT for uploads
headers,
body: buffer,
});
if (!response.ok) {
throw new Error(`Failed to upload image: ${response.status} - ${response.statusText}`);
}
res.locals.response = await response.json();
return next();
} catch (error: any) {
return next({
log: `Error uploading image to Cloudflare R2: ${error.message}`,
status: 500,
message: error,
});
}
};
Here is the error message:
Error uploading image to Cloudflare R2: Failed to upload image: 400 - Bad Request
Error:
{
log: 'Error uploading image to Cloudflare R2: Failed to upload image: 400 - Bad Request',
status: 500
}
On top of all of this, I have triple-checked that my headers are all correct with what cloudflare has given me.
What is the problem here?