Как запустить загрузку файла на стороне клиента, а не при отправке формы? - PullRequest
0 голосов
/ 25 сентября 2018

У меня есть рабочая версия примера активного хранилища с использованием s3, найденная здесь:

https://edgeguides.rubyonrails.org/active_storage_overview.html

Теперь я хочу иметь возможность выполнять загрузку файла не после завершения заполненияформа, но сразу после того, как пользователь выбирает файл для загрузки.На самом деле в моем случае у меня есть редактор wysiwyg, который имеет событие on drop , которое запускает

var myCodeMirror = CodeMirror.fromTextArea(post_body, {
   lineNumbers: true,
   dragDrop: true
  });

  myCodeMirror.on('drop', function(data, e) {
    var file;
    var files;
    // Check if files were dropped
    files = e.dataTransfer.files;
    if (files.length > 0) {
      e.preventDefault();
      e.stopPropagation();
      file = files[0];
      console.log('File: ' + file.name);
      console.log('File: ' + file.type);
      return false;
    }
  });

Так что, поскольку удаление файла вызывает это событие, я могу отправить этов active-storage как-нибудь, чтобы он сразу начал загружать файл в S3?

1 Ответ

0 голосов
/ 26 сентября 2018

Запуск загрузок со стороны клиента

Active Storage предоставляет класс JavaScript DirectUpload, который можно использовать для запуска загрузки файлов непосредственно со стороны клиента.

Вы можете использовать это для интеграции со сторонними плагинами (например, Uppy, Dropzone) или со своим собственным JS-кодом.

Использование DirectUpload

Первое, что вам нужно сделать, это убедиться, что AWS S3 настроен для обработки прямой загрузки.Это требует обеспечения правильной настройки конфигурации CORS.

Далее вы просто создаете экземпляр класса DirectUpload, передавая ему файл для загрузки и URL для загрузки.

import { DirectUpload } from "activestorage"

// your form needs the file_field direct_upload: true, which
// provides data-direct-upload-url
const input = document.querySelector('input[type=file]')
const url = input.dataset.directUploadUrl
const upload = new DirectUpload(file, url)

upload.create((error, blob) => { 
   // handle errors OR persist to the model using 'blob.signed_id'
})

См. Полную документацию здесь: https://edgeguides.rubyonrails.org/active_storage_overview.html#integrating-with-libraries-or-frameworks

Метод DirectUpload#create инициирует загрузку на S3 и возвращает с ошибкой или файлом загруженного файла.

Предполагая, что ошибок нет, последний шаг - сохранение загруженного файла в модель.Вы можете сделать это, используя blob.signed_id и поместив его в скрытое поле где-то на странице ИЛИ с AJAX-запросом на обновление вашей модели.

Загрузка файла по капле

В вышеописанном случае, чтобы начать прямую загрузку по капле, просто вставьте указанный выше код в обработчик drop.

Примерно так:

myCodeMirror.on('drop', function(data, e) {
   // Get the file
   var file = e.dataTransfer.files[0];

   // You need a file input somewhere on the page...
   const input = document.querySelector('input[type=file]')
   const url = input.dataset.directUploadUrl

   // Instantiate the DirectUploader object
   const upload = new DirectUpload(file, url)

   // Upload the file
   upload.create((error, blob) => { ... })
});

Использование конвейера ресурсов

Если вы просто используете конвейер ресурсов и не используете инструмент связывания JavaScript, то вы создаете экземплярыкласс DirectUpload вот так

const upload = new ActiveStorage.DirectUpload(file, url)

...