Добавить файлы в файл входного типа с несколькими перед загрузкой - PullRequest
0 голосов
/ 05 мая 2020

У меня есть форма на моем laravel веб-сайте с разделом, который позволяет пользователям загружать несколько файлов изображений (с предварительным просмотром выбранных изображений). Если пользователь выбирает несколько изображений только один раз, все работает, и выбранные изображения загружаются. Однако, если пользователь выбирает несколько изображений в двух разных случаях перед отправкой формы, будет загружена только последняя группа выбранных изображений.

Например; пользователь выбирает 4 изображения, затем заполняет некоторые другие поля формы, а затем решает добавить еще 3 изображения поверх 4 изображений, которые они ранее выбрали перед отправкой формы. Поле предварительного просмотра изображения будет содержать все 7 выбранных ими изображений, но как только они отправят форму, будут загружены только последние 3 изображения, которые они выбрали.

HTML Ввод нескольких файлов:

<input id="gphotos" type="file" name="gphotos[]" multiple>
<div class="preview"></div>

JavaScript:

function gphoto(input, ImagePreview) {
    if (input.files) {
        var fileAmount = input.files.length;

        for (i = 0; i < fileAmount; i++) {
            var reader = new FileReader();

            reader.onload = function(e) {
                $('.preview').css('margin-top', '4px');
                $($.parseHTML('<img class="gphoto">')).attr('src', e.target.result).appendTo(ImagePreview);
            }

            reader.readAsDataURL(input.files[i]);
        }
    }
};

$('#gphotos').change(function() {
    gphoto(this, 'div.preview');
});

Контроллер:

if (request('gphotos')) {
        $imageArray['gphotos'] = array();

        foreach (request()->gphotos as $gphoto) {
            $gphotoPath = $gphoto->store('gphotos', 'public');

            $imageArray['gphotos'][] =  $gphotoPath;
        }

        $imageArray['gphotos'] = json_encode($imageArray['gphotos']);
    }

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

Ответы [ 3 ]

0 голосов
/ 06 мая 2020

Вы можете добавить новый <input type="file"> всякий раз, когда закончите загрузку предыдущих файлов, и скрыть предыдущий ввод. Таким образом, вы продолжаете добавлять новый ввод каждый раз, когда хотите добавить больше файлов, и предотвращать перезапись предыдущего ввода.

И это не требует использования AJAX.

<form id="gphotos-form" enctype="multipart/form-data">
  <div class="gphotos-upload">
    <input class="gphotos" type="file" name="gphotos[]" multiple>
  </div>
  <div class="preview"></div>
  <button type="submit">Submit</button>
</form>
.ghpotos[hidden] {
  display: none;
}
let $uploads = $('.gphotos-upload');
let $preview = $('div.preview');

$('#gphotos-form').on('change', function(event) {

  let $currentInput = $(event.target);
  let $newInput = $('<input class="gphotos" type="file" name="gphotos[]" multiple>');

  for (const file of event.target.files) {
    const image = new Image();
    image.classList.add('gphoto');
    image.src = URL.createObjectURL(file);
    image.onload = event => {
      $preview.append(image);
      URL.revokeObjectURL(event.target.src);
    };
  }

  // Disabled and hide current input.
  $currentInput.attr('hidden', '');

  // Add new input to do another upload.
  $uploads.append($newInput);

});
0 голосов
/ 11 мая 2020

HTML Ввод нескольких файлов:

<input id="gphotos" type="file" name="gphotos[]" multiple>
<div class="store"></div>
<div class="preview"></div>

JavaScript:

function gphoto(input, ImagePreview) {
        var files = input.files;
        var filesArr = Array.prototype.slice.call(files);

        filesArr.forEach(function(f) {
            if (!f.type.match("image.*")) {
                return;
            }
            var reader = new FileReader();
            reader.onload = function(e) {
                $('.preview').css('margin-top', '4px');
                $($.parseHTML('<img class="gphoto">')).attr('src', e.target.result).appendTo(ImagePreview);
                $($.parseHTML('<input type="hidden" name="photos[]">')).attr('value', e.target.result).appendTo($('.store'));
            };
            reader.readAsDataURL(f);
        });
    }

    $('#gphotos').change(function() {
        gphoto(this, 'div.preview');
    });

Контроллер:

if (request('photos')) {
            $imageArray['gphotos'] = array();

            foreach (request()->photos as $gphoto) {
                $base64_str = substr($gphoto, strpos($gphoto, ",")+1);
                $gphotoPath = 'gphotos/'.\Str::random(11) . '.jpg';
                $gphoto = base64_decode($base64_str);
                \Storage::disk('public')->put($gphotoPath, $gphoto);

               $imageArray['gphotos'][] =  $gphotoPath;
            }

            $imageArray['gphotos'] = json_encode($imageArray['gphotos']);
        }
0 голосов
/ 05 мая 2020

Вместо того, чтобы позволять форме обрабатывать ее собственное представление, создайте свою собственную. Прослушивайте событие submit в форме и всякий раз, когда вы отправляете, отмените поведение по умолчанию и отправьте свои данные с помощью AJAX. В этом случае функция jQuery ajax. Отправьте его в файл PHP, который обрабатывает ваш входящий запрос.

Вы можете хранить файлы, например изображения, в объекте FormData. Это контейнер для установки пар ключ / значение для отправки с HTTP-запросом. Так что создайте его.

В вашем слушателе событий change вы захотите добавить каждое выбранное изображение в этот FormData контейнер, чтобы изображения сохранялись там. Таким образом, вы можете каждый раз выбирать новые изображения и добавлять их в контейнер. И когда вы отправляете, вы отправляете только этот контейнер с изображениями в них.

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

<form id="gphotos-form" enctype="multipart/form-data">
  <input id="gphotos" type="file" name="gphotos[]" multiple>
  <div class="preview"></div>
  <button type="submit">Submit</button>
</form>
// Container for the images.
const selectedImages = new FormData();

function gphoto(input, imagePreview) {
  for (const file of input.files) {
    const image = new Image();
    image.classList.add('gphoto');
    image.src = URL.createObjectURL(file);
    image.onload = event => {
      $(imagePreview).append(image);
      URL.revokeObjectURL(event.target.src);
    };

    // Image is added here.
    selectedImages.append('gphotos', file);

  }
}

$('#gphotos').on('change', function() {
  gphoto(this, 'div.preview');
});

$('#gphotos-form').on('submit', function(event) {

  // Get the data from the form, but remove the gphotos[] one,
  // because we want to use our own collection of images.
  const formData = new FormData(event.target);
  formData.delete('gphotos[]');
  for (const file of selectedImages.values()) {
    formData.append('gphotos', file);
  }

  // Send container to your server.
  // Change the url: value to your PHP script.
  $.ajax({
    url: 'http://example.com/script.php',
    data: formData,
    processData: false,
    contentType: false,
    type: 'POST',
    success: function(data){
      console.log(data);

      // Delete all the images from the container.
      for (let key of selectedImages.keys()) {
        selectedImages.delete(key)
      });

      // Clear the preview.
      $('div.preview').html('');

    }
  });

  event.preventDefault();

});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...