Ошибка при синтаксическом анализе изображения с серьезной ошибкой NodeJS Express MongoDB - PullRequest
0 голосов
/ 09 июля 2020

У меня возникла эта проблема, которой у меня никогда раньше не было, и я использовал эту же функцию для загрузки изображения и сохранения его в MongoDB целую вечность. Вот функция, которую я использую:

router.post("/profile-pic/:id", async (req, res, next) => {
    try {
        let user = await User.findById(req.params.id);
        if (!user) return res.status(404).send("User not found...");
        let form = new formidable.IncomingForm();
        form.keepExtensions = true;
        form.parse(req, async (err, fields, files) => {
            if (err) return res.status(400).send("Image could not be uploaded.");
            else if (files.profilePic) {
                if (files.profilePic.size > 1000000) {
                    return res.status(400).send("Image can not be larger than 1MB");
                }
                await User.findByIdAndUpdate({ _id: user.id }, {
                    profilePic: {
                        data: fs.readFileSync(files.profilePic.path),
                        contentType: files.profilePic.type
                    }
                }, { useFindAndModify: false });
                res.send("Image uploaded successfully.");
            }
        });
    } catch (ex) {
        console.error(ex);
        next();
    }
});

И вот та ошибка, которую я начал получать:

(node:10084) UnhandledPromiseRejectionWarning: CastError: Cast to Buffer failed for value "{
  data: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01 00 01 00 00 ff ed 00 9c 50 68 6f 74 6f 73 68 6f 70 20 33 2e 30 00 38 42 49 4d 04 04
00 00 00 00 00 80 ... 68443 more bytes>,
  contentType: 'image/jpeg'
}" at path "profilePic"
    at model.Query.exec (C:\Users\Lenovo\Desktop\InstaCringe\server\node_modules\mongoose\lib\query.js:4351:21)
    at model.Query.Query.then (C:\Users\Lenovo\Desktop\InstaCringe\server\node_modules\mongoose\lib\query.js:4443:15)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:10084) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10084) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will
terminate the Node.js process with a non-zero exit code.

EDIT Схема пользователя:

const userSchema = new mongoose.Schema({
    name: { type: String, trim: true, required: true, maxLength: 60 },
    email: { type: String, unique: true, trim: true, maxLength: 100 },
    password: String,
    isAdmin: { type: Boolean, default: false },
    profilePic: { type: Buffer, contentType: String },
    photos: Array
});

Кто-нибудь может помочь мне раскрыть этот кейс ... Я понятия не имею, почему я больше не могу загружать изображения. Заранее спасибо! :)

1 Ответ

0 голосов
/ 10 июля 2020

Почему возникает ошибка:

Несоответствие между тем, что есть в вашей схеме, и тем, что вы пытаетесь сохранить в базе данных. В частности, profilePic в вашей схеме определяется как:

profilePic: { type: Buffer, contentType: String }

Обратите внимание, что mon goose проигнорирует свойство contentType, поскольку это недопустимый вариант для типа Buffer. Почему пн goose рассматривает contentType как вариант? спросите вы; это потому, что когда Mon goose находит вложенное свойство с именем type в вашей схеме, Mon goose предполагает, что ему необходимо определить SchemaType с заданным типом, а все остальные свойства в объекте рассматриваются Параметры SchemaType для этого типа. Вы можете узнать больше о ключе type здесь .

В конечной точке post /profile-pic/:id вы пытаетесь сохранить это:

profilePic: {
  data: fs.readFileSync(files.profilePic.path),
  contentType: files.profilePic.type
}

Mon goose попытается преобразовать объект, который вы пытаетесь сохранить, в то, что было указано в схеме (буфер), однако он не может этого сделать, и поэтому вы получаете CastError.

Исправление:

  1. Если это вариант, удаление свойства contentType в схеме и непосредственное сохранение значения буфера было бы простым исправлением. Схема становится примерно такой:
profilePic: { type: Buffer }

И сохранение становится примерно таким:

profilePic: fs.readFileSync(files.profilePic.path),

теперь, profilePic будет содержать значение буфера изображения.

Однако, я предполагаю, что причина, по которой у вас было свойство contentType в первую очередь, заключалась в намеренном сохранении contentType значения буфера, если вас все еще интересует этот фрагмент данных, вам придется обновить свой схема, чтобы создать для него пространство, примерно так:
profilePic: { 
  data: { type: Buffer },
  contentType: String 
}

Обратите внимание, что, в отличие от ранее, contentType не объявлен как опция для типа Buffer, скорее, это вложенное свойство с собственным типом .

Теперь вы можете go заранее сохранить данные profilePic, как вы делали раньше:

profilePic: {
  data: fs.readFileSync(files.profilePic.path),
  contentType: files.profilePic.type
}
...