limit file type and file size using media_handle_upload

Use PHP

// Check that the nonce is valid, and the user can edit this post.
if (isset( $_POST['my_image_upload_nonce'] ) 
    && wp_verify_nonce( $_POST['my_image_upload_nonce'], 'my_image_upload' )
){

    // Input type file name
    $image_input_name="my_image_upload";

    // Allowed image types
    $allowed_image_types = array('image/jpeg','image/png');

    // Maximum size in bytes
    $max_image_size = 1000 * 1000; // 1 MB (approx)

    // Check if there's an image
    if (isset($_FILES[$image_input_name]['size']) && $_FILES[$image_input_name]['size'] > 0){

        // Check conditions
        if(in_array($_FILES[$image_input_name]['type'], $allowed_image_types)
            && $_FILES[$image_input_name]['size'] <= $max_image_size){

            // You shall pass

            // These files need to be included as dependencies when on the front end.
            require_once( ABSPATH . 'wp-admin/includes/image.php' );
            require_once( ABSPATH . 'wp-admin/includes/file.php' );
            require_once( ABSPATH . 'wp-admin/includes/media.php' );

            // Let WordPress handle the upload.
            // Remember, 'my_image_upload' is the name of our file input in our form above.
            $attachment_id = media_handle_upload($image_input_name , $post_id );

            if ( is_wp_error( $attachment_id ) ) {
                // There was an error uploading the image.
            } else {
                add_post_meta($post_id, 'post_image', $attachment_id, true);
            }

        } else {
            // You shall not pass
        }
    }
} else {
    // The security check failed, maybe show the user an error.
}