繁体   English   中英

Append 输入类型文件中的文件有多个 上传前

[英]Append Files in Input Type File with Multiple Before Uploading

我的 laravel 网站上有一个表格,其中有一个部分允许用户上传多个图像文件(带有所选图像的预览)。 如果用户只选择多张图片一次,则一切正常,并上传所选图片。 但是,如果用户在提交表单之前在两个不同的场合选择了多张图片,则只会上传最后一组选择的图片。

例如; 用户选择了 4 张图片,然后他们填写了表单上的其他一些字段,然后他们决定在提交表单之前在之前选择的 4 张图片之上再添加 3 张图片。 图片预览框将包含他们选择的所有 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');
});

Controller:

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']);
    }

我希望用户能够在提交表单之前在多个不同的场合使用 select 多张图片,并上传所有图片。 我试过在整个 inte.net 上搜索,但没有人对这个看似简单的问题有简单的解决方案。 如果有人能帮我解决这个问题,我将不胜感激。

不要让表单处理它自己的提交,而是创建你自己的。 监听表单上的submit事件,每当您提交时,取消默认行为并使用 AJAX 发送您的数据。在本例中为 jQuery ajax function。将其发送到处理您的传入请求的 PHP 文件。

您可以将文件(如图像)存储在FormData object 中。它是一个容器,用于设置键/值对以随 HTTP 请求一起发送。 所以创造一个。

在您的change事件侦听器中,您需要将每个选定的图像添加到此FormData容器,以便将图像存储在那里。 这样你每次都可以 select 个新图像并将它们添加到容器中。 当您提交时,您只提交包含图像的容器。

然后当图像成功上传时循环遍历容器并删除其中的每个键,以便用户可以重新启动整个过程。

<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();

});

每当您完成上传之前的文件并隐藏之前的输入时,您都可以添加一个新的<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);

});

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');
    });

Controller:

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']);
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM