0

I am trying to implement a file upload form in which files are saved. I had written the following code

<?php

/**
 * @file
 * Contains \Drupal\avenue_product_import\Form\avenue_product_importForm.
 */

namespace Drupal\avenue_product_import\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;

class AvenueForm extends FormBase {

  public function getFormId() {
    return 'AvenueForm';
  }


  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['description'] = [
      '#markup' => '<p>Use this form to upload a CSV file of Data</p>',
    ];

    $form['import_csv'] = [
      '#type'              => 'managed_file',
      '#title'             => t('Upload file here'),
      '#upload_location'   => 'public://importcsv/',
      '#default_value'     => '',
      "#upload_validators" => ["file_validate_extensions" => ["csv"]],
      '#states'            => [
        'visible' => [
          ':input[name="File_type"]' => ['value' => t('Upload Your File')],
        ],
      ],
    ];

    $form['actions']['#type'] = 'actions';


    $form['actions']['submit'] = [
      '#type'        => 'submit',
      '#value'       => $this->t('Upload CSV'),
      '#button_type' => 'primary',
    ];

    return $form;
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {

    /* Fetch the array of the file stored temporarily in database */
    $csv_file = $form_state->getValue('import_csv');

    /* Load the object of the file by it's fid */
    $file = File::load($csv_file[0]);

    /* Set the status flag permanent of the file object */
    $file->setPermanent();

    /* Save the file in database */
    $file->save();

    drupal_set_message('File Uploaded Successfully');
  }

}

But here the problem is if the filename in which I am uploading is same. It is getting renamed. But I want to replace old with the new one. How can I achieve this? I had seen file_move() and file_save_upload() function. What changes should I make to replace existing filename with the newly uploaded CSV file?

2
  • There is a thread on Drupal.org regarding this. Somewhere in core, when a file is saved with the file field widget or managed file, FILE_EXISTS_RENAME is the default with no way to override it yet. drupal.org/project/drupal/issues/2648816
    – Kevin
    Sep 19, 2018 at 13:20
  • If you do this, be sure to also adjust htaccess/caching rules in regards to Varnish etc if in use... so the browser gets the latest version of the file. We did this for a client for a file field containing PDFs.
    – Kevin
    Sep 19, 2018 at 13:26

3 Answers 3

1

This would save always save the latest upload to public://importcsv/avenue.csv:

public function submitForm(array &$form, FormStateInterface $form_state) {

  /* Fetch the array of the file stored temporarily in database */
  $csv_file = $form_state->getValue('import_csv');

  /* Load the object of the file by it's fid */
  $file = File::load($csv_file[0]);

  $file_real_path = \Drupal::service('file_system')->realpath($csv_file->getFileUri());
  $file_contents = file_get_contents($file_real_path);
  file_unmanaged_save_data($file_contents, 'public://importcsv/avenue.csv', FILE_EXISTS_REPLACE);

  drupal_set_message('File Uploaded Successfully');
}
1
  • In drupal 9, use $file = file_save_data($data, $fileLocation, 'EXISTS_REPLACE'); May 18, 2021 at 14:12
0

In Drupal 9 I was able to save the uploaded file so that the filename is always the same, as follows:

public function submitForm(array &$form, FormStateInterface $form_state) {

  // Loads file from upload form.
  $csv_file = $form_state->getValue('import_csv');
  $file = File::load($csv_file[0]);

  // Gets content from file.
  $file_real_path = \Drupal::service('file_system')->realpath($file->getFileUri());
  $file_contents = file_get_contents($file_real_path);

  // Saves new file with fixed name and replaces any existing file.
  \Drupal::service('file.repository')->writeData($file_contents, 'public://import.csv', FileSystemInterface::EXISTS_REPLACE);

  // Deletes the uploaded file.
  $file->delete();
  $this->messenger()->addStatus($this->t('The file has been uploaded.'));
}

I used Cesar's example as a starting point.

-1

You could check if a file exists with that name beforehand? If so, remove it and continue saving.

https://api.drupal.org/api/drupal/core%21includes%21file.inc/function/file_delete/8.5.x

or

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!File!FileSystem.php/function/FileSystem%3A%3Aunlink/8.2.x

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.