在 Node JS 中将(缓冲区)图像文件上传到 Cloudinary 时出现错误

问题描述 投票:0回答:1

当我尝试将图像文件(缓冲区)上传到 Cloudinary 时,我的代码中出现一些错误。

const cloudinary = require("cloudinary").v2;

但是当我将图像存储在 MongoDB 数据库中时,它存储得很好。我创建了一个用户注册流程。当用户输入信息并尝试注册时,将生成一个令牌并将其存储在数据库中。但在将用户信息存储到数据库之前,我想将用户图像文件存储到 Cloudinary 并将其 URL 存储到数据库中。当我尝试这样做时,我收到错误。这是我的代码...

进程寄存器

const image = req.file;
    if (!image) {
      throw createHttpError(400, "Image file is required");
    }

    if (image) {
      if (image.size > 1024 * 1024 * 2) {
        throw createHttpError(
          400,
          "File is too large. It must be less than 2 MB"
        );
      }
    }

    // buffer
    const imageBufferString = req.file.buffer.toString("base64");
// create jwt
    const tokenPayload = {
      username,
      email,
      password,
      phone,
      address,
      image: imageBufferString,
    };

   const token = createJSONWebToken(tokenPayload, jwtActivisionKey, "10m");

验证用户

try {
    const token = req.body.token;
    if (!token) throw createHttpError(404, "Token not found!");
    try {
      // verify user and register
      const decoded = jwt.verify(token, jwtActivisionKey);
      if (!decoded) throw createHttpError(401, "Unable to verify user");
      // console.log(decoded);

      const userExists = await User.exists({ email: decoded.email });
      if (userExists) {
        throw createHttpError(
          409,
          "User with this email already exists. Please login"
        );
      }

     const image = decoded.image;   // declaring image from the token
      
      // if (image) {
      //   const uploadResult = cloudinary.uploader.upload_stream(
      //     image,
      //     { folder: "Mern" },
      //     function (error, result) {
      //       console.log(error, result);
      //     }
      //   );
      //   return streamifier.createReadStream(image).pipe(uploadResult);
      // }

      await new Promise((resolve) => {
        const uploadResult = cloudinary.uploader
          .upload_stream(
            { folder: "Mern", resource_type: "image" },
            (error, result) => {
              if (result) {
                console.log(result);
                return resolve(result);
              }
              console.log(error);
            }
          )
          .end(image);
        streamifier.createReadStream(image.buffer).pipe(uploadResult);
        // decoded.image = uploadResult.secure_url;
      });

      // and then create user
      const user = await User.create(decoded);

      return successResponse(res, {
        statusCode: 201,
        message: "User was registered successfully",
        payload: user,
      });
    } catch (error) {
      if (error.name === "TokenExpiredError") {
        throw createHttpError(401, "Token has expired");
      } else if (error.name === "JsonWebTokenError") {
        throw createHttpError(401, "Invalid Token");
      } else {
        throw error;
      }
    }
  } catch (error) {
    next(error);
    console.log(error.message);
  }

文件上传

const multer = require("multer");

const MAX_FILE_SIZE = 2097152; // 2mb -- 1024bytes * 1024kb * 2
const ALLOWED_FILE_TYPES = ["image/jpg", "image/jpeg", "image/png"];
const UPLOAD_USER_IMG_DIR = "public/images/users";

// for user image
const userStorage = multer.memoryStorage();

const fileFilterUser = (req, file, cb) => {
  if (!file.mimetype.startsWith("image/")) {
    return cb(new Error("Only image files are allowed"), false);
  }
  if (file.size > MAX_FILE_SIZE) {
    return cb(new Error("File size exceeds the maximum limit"), false);
  }
  if (!ALLOWED_FILE_TYPES.includes(file.mimetype)) {
    return cb(new Error("File type is not allowed"), false);
  }
  cb(null, true);
};

const uploadUserImage = multer({
  storage: userStorage,
  fileFilter: fileFilterUser,
});

用户路由器

userRouter.post(
  "/process-register",
  uploadUserImage.single("image"),
  isLoggedOut,
  validateUserRegistration,
  runValidation,
  handleProcessRegister
);
userRouter.post("/activate", isLoggedOut, handleActivateUserAccount);

console.log 输出...

{ message: 'Invalid image file', name: 'Error', http_code: 400 }

当我更改代码时,控制台中出现了不同的错误......

TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received undefined
The "path" argument must be of type string or an instance of Buffer or URL. Received undefined
{ message: 'empty file', name: 'error', http_code: 400 }

node.js mongodb express multer cloudinary
1个回答
0
投票

终于解决了错误...

我收到错误是因为我尝试将二进制图像直接编码到 JWT 中。当我尝试这样做时,二进制数据的有效负载变得更大。此外,从 JWT 和用户验证中解码二进制图像(JWT 无法解码精确的大二进制数据)也是一个问题。 JWT 不适合大负载。这不仅可能导致大小问题,还会导致解码和处理二进制数据时出现问题。 然后我应用了一些流程:

步骤:1

我。首先,将图像上传到Cloudinary。

 // Utility function to upload to Cloudinary
const uploadToCloudinary = (bufferImage) => {
  return new Promise((resolve, reject) => {
    const stream = cloudinary.uploader.upload_stream(
      { resource_type: "image", visibility: "public" },
      (error, result) => {
        if (error) reject(error);
        else resolve(result);
      }
    );
    streamifier.createReadStream(bufferImage).pipe(stream);
  });
};

module.exports = uploadToCloudinary;

ii.获取图像 URL:上传后,Cloudinary 会提供一个响应,其中包含上传图像的 URL。

*从 userController 上传图像...

const image = req.file;
if (!image) {
  throw createHttpError(400, "Image file is required");
}    
// buffer
const bufferImage = image.buffer;
// uploading image to cloudinary and collect its URL to encode it to the JWT
const result = await uploadToCloudinary(bufferImage);
if (!result || !result.secure_url) {
  throw new Error("Failed to upload image to Cloudinary.");
}
const imageUrl = result.secure_url;

iii.然后在 JWT 中对图像 URL 进行编码(创建一个在其负载中包含图像 URL 的 JWT)。

// create jwt
const tokenPayload = {
  username,
  email,
  password,
  phone,
  address,
  image: imageUrl,
};
const token = createJSONWebToken(tokenPayload, jwtActivisionKey, "10m");

步骤:2 通过解码令牌并提取图像 URL 来解码 JWT 并处理用户验证。

// verify user and register
  const decoded = jwt.verify(token, jwtActivisionKey);
  if (!decoded) throw createHttpError(401, "Unable to verify user");
  
  const imageUrl = decoded.image;
  console.log(imageUrl);

   // and then create user
  const user = await User.create(decoded);
© www.soinside.com 2019 - 2024. All rights reserved.