Search code examples
node.jsmongodbfluttermongoosebackend

how to update data using Nodejs in mongodb


I use nodejs & MongoDB for backend and Flutter for front end. so i'm trying to update details of the user. This is update details function of the user in NodeJs. (user can update his profile image also.)

const updateUser = asyncHandler(async (req, res, next) => {

    // Extract the JSON data from the request body
    const { name, email, phone, address, password } = req.body;

    // Update the user with the new data
    const userId = req.params.id;
    const user = await User.findById(userId);

    if (!user) {
      res.status(404);
      throw new Error("User not found.");
    }
    console.log(name);
    user.name = name || user.name;
    user.email = email || user.email;
    user.phone = phone || user.phone;
    user.address = address || user.address;

    if (password) {
      user.password = await bcrypt.hash(password, 10);
    }

    if (req.file) {
      user.imageUrl = req.file.path;
    }

    user.save()
      .then((response) => {
        res.json({
          message: "User updated.",
          user: user,
        });
      })
      .catch((error) => {
        res.status(400);
        throw new Error("Error updating user.");
      });
      console.log(user);
  });

When using postman for testing, the function is working properly but after connect the front end user details is not updating. but return the message, succefully updated. this is frondend updating function.

  static Future<String> updateUser({required User user}) async {
    String? token = await StoreToken.getToken();

    final request = http.MultipartRequest(
      'PUT',
      Uri.http(Config.apiURL, Config.updateUser(id: user.id.toString())),
    );

    request.headers.addAll({
      'Content-Type': 'multipart/form-data',
      'Authorization': 'Bearer $token',
    });

    if (user.imageUrl != "" && user.imageUrl != null && !user.imageUrl.toString().contains("profiles")) {
      print('Adding image to request...');
      request.files.add(await http.MultipartFile.fromPath(
        'imageUrl',
        user.imageUrl.toString(),
      ));
    }

    request.fields.addAll({
      'name': user.name,
      'email': user.email,
      'phone': user.phone,
      'address':user.address.toString(),
    });

    final response = await request.send();

    if (response.statusCode != 200) {
      throw Exception('Failed to update user');
    }

    final responseString = await response.stream.bytesToString();
    print(responseString);
    return responseString;
  }

then I remove the http.MultipartRequest and use http.Request without updating image. user details are updated. Anyone can help me to solve this problem.


Solution

  • Node js side

    import mime from 'mime'
    import fs from 'fs'
    
    function decodeBase64Image(dataString) {
    
    var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/),
        response = {}
    if (matches.length !== 3) {
        return new Error('Invalid input string')
    }
    response.type = matches[1]
    response.data = new Buffer.from(matches[2], 'base64')
    return response
    }
    
    
    
    const saveUserProfile = asyncHandler(async (req, res) => {
     var {
        userId,
        userImage
    } = req.body;
    
    
    var decodedImg = decodeBase64Image(userImage)
            var imageBuffer = decodedImg.data
            var type = decodedImg.type
            var extension = mime.getExtension(type)
            var fileName = (new Date()).getTime().toString(36) + Math.random().toString(36).slice(2) + '.' + extension
     fs.writeFileSync(__dirname + '/' + profilePicDir + '/' + fileName, imageBuffer, 'utf8')
    
    })
    

    Fullter side

     File file = File(_imagePath);
    Uint8List bytes = file.readAsBytesSync();
    String base64Image = base64Encode(bytes);
    print(base64Image);
    

    first image file convert to base64 string to request on node side