Обновить изображение из внешнего интерфейса

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

Вот коды:

Внешний интерфейс

Здесь я отправляю запрос на обновление имени, электронной почты и изображения

const userDataForm = document.querySelector('.profile-update');

if (userDataForm)
  userDataForm.addEventListener('submit', async (e) => {
    e.preventDefault();
    const name = document.getElementById('nameInput').value;
    const email = document.getElementById('emailInput').value;
    const image = document.getElementById('profile-img-file-input').files[0];

    try {
      const res = await fetch('/api/v1/users/updateMe', {
        method: 'PATCH',
        body: JSON.stringify({ name, email, image }),
        headers: { 'Content-Type': 'application/json' },
      });
      console.info(res);
      const data = await res.json(); 
      if (data.status == 'success') {
        alert('success');
      }
    } catch (error) {
      alert(error);
    }
  });

profile.ejs

Вот страница ejs

        <div class = "profile-user position-relative d-inline-block mx-auto mb-4">
                   <img
                          src = "/assets/img/<%= user.photo %>"
                          id = "user-profile-image"
                          class = "rounded-circle avatar-xl img-thumbnail user-profile-image"
                          alt = "user-profile-image"
                     />
                     <div class = "avatar-xs p-0 rounded-circle profile-photo-edit">
                          <input
                            id = "profile-img-file-input"
                            name = "photo"
                            accept = "image/*"
                            type = "file"
                            class = "profile-img-file-input"
                        />
                       <label for = "profile-img-file-input" class = "profile-photo-edit avatar-xs">
                            <span class = "avatar-title rounded-circle bg-light text-body">
                              <i class = "ri-camera-fill"></i>
                            </span>
                        </label>
                     </div>
        </div>

Внутренний код

Вот контроллер для загрузки изображения и обновления имени, электронной почты и изображения.


const multerStorage = multer.memoryStorage();

const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith('image')) {
    cb(null, true);
  } else {
    cb(new AppError('not an image! please upload only images', 400), false);
  }
};
// const upload = multer({ dest: 'public/img/users' });
const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter,
});

exports.uploadUserPhoto = upload.single('photo');

exports.resizeUserPhoto = catchAsync(async (req, res, next) => {
  if (!req.file) return next();
  req.file.filename = `user-${req.user.id}-${Date.now()}.jpeg`;

  await sharp(req.file.buffer)
    .resize(500, 500)
    .toFormat('jpeg')
    .jpeg({ quality: 90 })
    .toFile(`public/assets/img/${req.file.filename}`);
  next();
});

const filterObj = (obj, ...allowedFields) => {
  const newObj = {};
  Object.keys(obj).forEach((el) => {
    if (allowedFields.includes(el)) newObj[el] = obj[el];
  });

  return newObj;
};


exports.updateMe = async (req, res, next) => {
  // console.info('the filename', req.file);
  // console.info(req.body);
  // Create an error if a user POSTs password data

  if (req.body.password || req.body.passwordConfirm) {
    return next(new AppError('This route is not for password update Please use /updateMyPassword', 400));
  }
  // Update user document
  // const user = await User.findById(req.user.id);

  // Filterd out unwanted fields that are not allowed to be
  // updated
  const filteredBody = filterObj(req.body, 'name', 'email');
  if (req.file) filteredBody.photo = req.file.filename;

  // update the user
  const updatedUser = await User.findByIdAndUpdate(req.user._id, filteredBody, {
    new: true,
    runValidators: true,
  });

  res.status(200).json({
    status: 'success',
    data: {
      user: updatedUser,
    },
  });
};

вот файл маршрута

router.patch('/updateMe', userController.uploadUserPhoto, userController.resizeUserPhoto, userController.updateMe);

Вы не можете помещать двоичные файлы (например, изображения) в JSON вот так. multer не работает с JSON, он работает с multipart/form-data, который вы должны использовать вместо JSON.

Evert 01.04.2023 09:58

Спасибо, это помогло мне найти решение

Tosin 01.04.2023 12:14
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, решение состояло в том, чтобы использовать API данных формы, который позволяет нам отправлять multipart/form-data (что помогает загружать файлы через форму)

эта статья мне тоже помогла https://blog.logrocket.com/multer-nodejs-express-upload-file/

const userDataForm = document.querySelector('.profile-update');

if (userDataForm)
  userDataForm.addEventListener('submit', async (e) => {
    e.preventDefault();

    const form = new FormData();
    console.info(form);
    form.append('name', document.getElementById('nameInput').value);
    form.append('email', document.getElementById('emailInput').value);
    form.append('photo', document.getElementById('profile-img-file-input').files[0]);

    console.info(form);
    try {
      const res = await fetch('/api/v1/users/updateMe', {
        method: 'PATCH',
        body: form,
      });
      console.info(res);

      const data = await res.json();
      console.info(data);
      console.info(form);
      if (data.status == 'success') {
        showAlert('success', 'Profile successfully updated');
        window.location.reload();
      }
    } catch (error) {
      alert(error);
    }
  });

Другие вопросы по теме