Add fields to a coded block and use them in a templated block
Probably the easiest way to do this is a block with a settings form.

When you place a block of this class via the block layout, you can add your information in the settings.  To have another block with different settings, just place another block.

Some sample code:

 public function blockForm($form, FormStateInterface $form_state) {
    $form = parent::blockForm($form, $form_state);

    $config = $this-&gt;getConfiguration();

    $form['my_block_text'] = array(
      '#type' =&gt; 'textfield',
      '#title' =&gt; $this-&gt;t('Foo'),
      '#description' =&gt; $this-&gt;t('my desc'),
      '#default_value' =&gt; isset($config['my_block_text']) ? $config['my_block_text'] : '',
    );
    return $form;
  }
  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    parent::blockSubmit($form, $form_state);
    $values = $form_state-&gt;getValues();
    $this-&gt;configuration['my_block_text'] = $values['my_block_text'];
  }
  public function build() {
    $config = $this-&gt;getConfiguration();
    $text = $config['my_block_text'];
    ...
  $block = [
   '#theme' =&gt; 'my_module_my_theme',
    '#my_text' =&gt; $text,
    ... 
  ]; 
  return $block;
}


For images / files, you can just use the standard file form type.  The config will get the fid of the image.  In the build, you will need to load the file entity and generate the URL to the file.  (Lots of existing examples of this).

To get it all to twig, you will need to use a hook_template() implementation that defines the twig template and variables. Then pass it to the theme using the render array created in the block build code.