HTML5, JavaScript: перетаскивание файла из внешнего окна (проводник Windows)

Это лучший сценарий для использования CoordinatorLayout в вашем приложении. КоординаторLayout представляет собой супермощный FrameLayout, который имеет множество отличных анимационных трюков на рукавах.

Библиотека Design представляет интерфейс CoordinatorLayout, который обеспечивает дополнительный уровень контроля над событиями касания между дочерними просмотров, что многие из компонентов библиотеки Design используют.

Вы можете начать с этого и этого учебника .

29
задан Bunkai.Satori 21 April 2012 в 18:56
поделиться

4 ответа

Эта ссылка объясняет мой вопрос довольно подробно:

http://www.html5rocks.com/en/tutorials/file/dndfiles/

15
ответ дан Bunkai.Satori 21 April 2012 в 18:56
поделиться

Вот очень простой пример. Это показывает красный квадрат. Если вы перетащите изображение на красный квадрат, оно добавит его к телу. Я подтвердил, что он работает в IE11, Chrome 38 и Firefox 32. Более подробное объяснение см. В статье Html5Rocks .

var dropZone = document.getElementById('dropZone');

// Optional.   Show the copy icon when dragging over.  Seems to only work for chrome.
dropZone.addEventListener('dragover', function(e) {
    e.stopPropagation();
    e.preventDefault();
    e.dataTransfer.dropEffect = 'copy';
});

// Get file data on drop
dropZone.addEventListener('drop', function(e) {
    e.stopPropagation();
    e.preventDefault();
    var files = e.dataTransfer.files; // Array of all files

    for (var i=0, file; file=files[i]; i++) {
        if (file.type.match(/image.*/)) {
            var reader = new FileReader();

            reader.onload = function(e2) {
                // finished reading file data.
                var img = document.createElement('img');
                img.src= e2.target.result;
                document.body.appendChild(img);
            }

            reader.readAsDataURL(file); // start reading the file data.
        }
    }
});
<div id="dropZone" style="width: 100px; height: 100px; background-color: red"></div>
78
ответ дан John Weisz 21 April 2012 в 18:56
поделиться

Посмотрите на событие. Вы можете просто иметь внутреннюю часть div, которая будет скрыта до тех пор, пока событие ondragover не запустит функцию, которая покажет div с внутри него, что позволяет пользователю перетаскивать файл. Наличие декларации onchange позволяет автоматически вызывать функцию (например, выгрузку) при добавлении файла к входным данным. Убедитесь, что ввод допускает несколько файлов, так как вы не можете контролировать, сколько они будут пытаться перетащить в браузер.

3
ответ дан Charles John Thompson III 21 April 2012 в 18:56
поделиться

Принятый ответ предоставляет отличную ссылку на эту тему; однако, согласно правилам SO, следует избегать чистых ссылок, поскольку они могут исчезнуть в любое время. По этой причине я нашел время, чтобы обобщить содержание ссылки для будущих читателей.


Начало работы

Прежде чем внедрять метод загрузки файлов на свой веб-сайт, вы должны убедиться, что браузеры, которые вы выбираете для поддержки, будут в состоянии полностью поддерживать File API ]. Вы можете быстро проверить это с помощью фрагмента Javascript ниже:

// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
  // Great success! All the File APIs are supported.
} else {
  alert('The File APIs are not fully supported in this browser.');
}

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


Ввод формы

Самый распространенный способ загрузки файла - использовать стандартный элемент <input type="file">. JavaScript возвращает список выбранных объектов File как FileList.

  function handleFileSelect(evt) {
    var files = evt.target.files; // FileList object

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
      output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
                  f.size, ' bytes, last modified: ',
                  f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
                  '</li>');
    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>

Перетаскивание

Внесение простых изменений в приведенный выше фрагмент кода позволяет нам предоставить поддержка перетаскивания.

  function handleFileSelect(evt) {
    evt.stopPropagation();
    evt.preventDefault();

    var files = evt.dataTransfer.files; // FileList object.

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
      output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
                  f.size, ' bytes, last modified: ',
                  f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
                  '</li>');
    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
  }

  function handleDragOver(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
  }

  // Setup the dnd listeners.
  var dropZone = document.getElementById('drop_zone');
  dropZone.addEventListener('dragover', handleDragOver, false);
  dropZone.addEventListener('drop', handleFileSelect, false);
<div id="drop_zone">Drop files here</div>
<output id="list"></output>

Чтение файлов

Теперь вы получили ссылку на File Вы можете создать экземпляр FileReader для чтения его содержимого в память. Когда загрузка завершается, вызывается событие onload, и его атрибут result может использоваться для доступа к данным файла. Не стесняйтесь смотреть ссылки на FileReader, чтобы охватить четыре доступных варианта для чтения файла.

В приведенном ниже примере отфильтровываются изображения по выбору пользователя, вызывается reader.readAsDataURL() для файла и отображается миниатюра путем установки атрибута src для URL-адреса данных.

  function handleFileSelect(evt) {
    var files = evt.target.files; // FileList object

    // Loop through the FileList and render image files as thumbnails.
    for (var i = 0, f; f = files[i]; i++) {

      // Only process image files.
      if (!f.type.match('image.*')) {
        continue;
      }

      var reader = new FileReader();

      // Closure to capture the file information.
      reader.onload = (function(theFile) {
        return function(e) {
          // Render thumbnail.
          var span = document.createElement('span');
          span.innerHTML = ['<img class="thumb" src="', e.target.result,
                            '" title="', escape(theFile.name), '"/>'].join('');
          document.getElementById('list').insertBefore(span, null);
        };
      })(f);

      // Read in the image file as a data URL.
      reader.readAsDataURL(f);
    }
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
  .thumb {
    height: 75px;
    border: 1px solid #000;
    margin: 10px 5px 0 0;
  }
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>

Нарезка

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

Следующий пример демонстрирует чтение фрагментов файла. Стоит отметить, что он использует onloadend и проверяет evt.target.readyState вместо использования события onload.

  function readBlob(opt_startByte, opt_stopByte) {

    var files = document.getElementById('files').files;
    if (!files.length) {
      alert('Please select a file!');
      return;
    }

    var file = files[0];
    var start = parseInt(opt_startByte) || 0;
    var stop = parseInt(opt_stopByte) || file.size - 1;

    var reader = new FileReader();

    // If we use onloadend, we need to check the readyState.
    reader.onloadend = function(evt) {
      if (evt.target.readyState == FileReader.DONE) { // DONE == 2
        document.getElementById('byte_content').textContent = evt.target.result;
        document.getElementById('byte_range').textContent = 
            ['Read bytes: ', start + 1, ' - ', stop + 1,
             ' of ', file.size, ' byte file'].join('');
      }
    };

    var blob = file.slice(start, stop + 1);
    reader.readAsBinaryString(blob);
  }
  
  document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
    if (evt.target.tagName.toLowerCase() == 'button') {
      var startByte = evt.target.getAttribute('data-startbyte');
      var endByte = evt.target.getAttribute('data-endbyte');
      readBlob(startByte, endByte);
    }
  }, false);
  #byte_content {
    margin: 5px 0;
    max-height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
  }
  #byte_range { margin-top: 5px; }
<input type="file" id="files" name="file" /> Read bytes: 
<span class="readBytesButtons">
  <button data-startbyte="0" data-endbyte="4">1-5</button>
  <button data-startbyte="5" data-endbyte="14">6-15</button>
  <button data-startbyte="6" data-endbyte="7">7-8</button>
  <button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>

Мониторинг прогресса

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

События onloadstart и onprogress могут использоваться для отслеживания хода чтения.

Пример ниже демонстрирует отображение индикатора выполнения для контроля состояния чтения. Чтобы увидеть индикатор прогресса в действии, попробуйте большой файл или файл с удаленного диска.

  var reader;
  var progress = document.querySelector('.percent');

  function abortRead() {
    reader.abort();
  }

  function errorHandler(evt) {
    switch(evt.target.error.code) {
      case evt.target.error.NOT_FOUND_ERR:
        alert('File Not Found!');
        break;
      case evt.target.error.NOT_READABLE_ERR:
        alert('File is not readable');
        break;
      case evt.target.error.ABORT_ERR:
        break; // noop
      default:
        alert('An error occurred reading this file.');
    };
  }

  function updateProgress(evt) {
    // evt is an ProgressEvent.
    if (evt.lengthComputable) {
      var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
      // Increase the progress bar length.
      if (percentLoaded < 100) {
        progress.style.width = percentLoaded + '%';
        progress.textContent = percentLoaded + '%';
      }
    }
  }

  function handleFileSelect(evt) {
    // Reset progress indicator on new file selection.
    progress.style.width = '0%';
    progress.textContent = '0%';

    reader = new FileReader();
    reader.onerror = errorHandler;
    reader.onprogress = updateProgress;
    reader.onabort = function(e) {
      alert('File read cancelled');
    };
    reader.onloadstart = function(e) {
      document.getElementById('progress_bar').className = 'loading';
    };
    reader.onload = function(e) {
      // Ensure that the progress bar displays 100% at the end.
      progress.style.width = '100%';
      progress.textContent = '100%';
      setTimeout("document.getElementById('progress_bar').className='';", 2000);
    }

    // Read in the image file as a binary string.
    reader.readAsBinaryString(evt.target.files[0]);
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
  #progress_bar {
    margin: 10px 0;
    padding: 3px;
    border: 1px solid #000;
    font-size: 14px;
    clear: both;
    opacity: 0;
    -moz-transition: opacity 1s linear;
    -o-transition: opacity 1s linear;
    -webkit-transition: opacity 1s linear;
  }
  #progress_bar.loading {
    opacity: 1.0;
  }
  #progress_bar .percent {
    background-color: #99ccff;
    height: auto;
    width: 0;
  }
<input type="file" id="files" name="file" />
<button onclick="abortRead();">Cancel read</button>
<div id="progress_bar"><div class="percent">0%</div></div>
2
ответ дан PerpetualJ 21 April 2012 в 18:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: