Simular evento de arquivo suspenso

É possível simular / falsificar o evento drop usando somente o javascript? Como testar esse tipo de evento?

Tomemos por exemplo esta página de amostra de upload dnd, é possível acionar o evento “drop” com um arquivo sem realmente derrubar um arquivo lá? Vamos dizer clicando em um botão?

Eu comecei a escrever um script Sukuli que pode controlar o mouse e fazer o truque, mas eu estava procurando uma solução melhor.

EDITAR

@kol resposta é uma boa maneira de se livrar do evento arrastar e soltar, mas ainda tenho que selecionar manualmente um arquivo do meu computador. Este é o bit que eu estou interessado em simular. Existe uma maneira de criar uma variável de arquivo programaticamente?

var fileInput = document.getElementById('fileInput'), file = fileInput.files[0]; 

1. Eliminar a imagem selecionada pelo usuário

Eu fiz um jsfiddle . É uma versão simplificada da página html5demos.com que você mencionou, mas:

  • Eu adicionei uma tag que pode ser usada para selecionar um arquivo de imagem do computador local, e
  • Também adicionei uma tag com um manipulador onclick , que simula o evento “drop file” chamando diretamente o manipulador de events ondrop da tag div DND-target.

O manipulador ondrop parece com isso:

 holder.ondrop = function (e) { this.className = ''; e.preventDefault(); readfiles(e.dataTransfer.files); } 

Ou seja, temos que passar um argumento para ondrop , que

  • tem um campo dataTransfer com um subcampo de array de files , que contém o File selecionado, e
  • tem um método preventDefault (uma function que nenhum corpo fará).

Portanto, o manipulador onclick do botão “Simular queda” é o seguinte:

 function simulateDrop() { var fileInput = document.getElementById('fileInput'), file = fileInput.files[0]; holder.ondrop({ dataTransfer: { files: [ file ] }, preventDefault: function () {} }); } 

Teste

  1. Selecione um arquivo de imagem (png, jpeg ou gif)
  2. Clique no botão “Simular queda”

Resultado

Resultado

2. Eliminar ficheiros de teste gerados automaticamente sem interação do utilizador ( GOOGLE CHROME SOMENTE !!! )

Eu fiz outro jsfiddle . Quando a página é carregada, uma function é chamada, que:

  • cria um arquivo de texto no sistema de arquivos temporário e
  • carrega e solta este arquivo de texto no destino

    ; então

  • cria um arquivo de imagem no sistema de arquivos temporário e
  • carrega e solta esse arquivo de imagem no destino

    .

O código desta chamada de function do simulador de quedas é o seguinte:

 (function () { var fileErrorHandler = function (e) { var msg = ""; switch (e.code) { case FileError.QUOTA_EXCEEDED_ERR: msg = "QUOTA_EXCEEDED_ERR"; break; case FileError.NOT_FOUND_ERR: msg = "NOT_FOUND_ERR"; break; case FileError.SECURITY_ERR: msg = "SECURITY_ERR"; break; case FileError.INVALID_MODIFICATION_ERR: msg = "INVALID_MODIFICATION_ERR"; break; case FileError.INVALID_STATE_ERR: msg = "INVALID_STATE_ERR"; break; default: msg = "Unknown Error"; break; }; console.log("Error: " + msg); }, requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem, dropFile = function (file) { holder.ondrop({ dataTransfer: { files: [ file ] }, preventDefault: function () {} }); }; if (!requestFileSystem) { console.log("FileSystem API is not supported"); return; } requestFileSystem( window.TEMPORARY, 1024 * 1024, function (fileSystem) { var textFile = { name: "test.txt", content: "hello, world", contentType: "text/plain" }, imageFile = { name: "test.png", content: "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", contentType: "image/png", contentBytes: function () { var byteCharacters = atob(this.content), byteArrays = [], offset, sliceSize = 512, slice, byteNumbers, i, byteArray; for (offset = 0; offset < byteCharacters.length; offset += sliceSize) { slice = byteCharacters.slice(offset, offset + sliceSize); byteNumbers = new Array(slice.length); for (i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } return byteArrays; } }; // Create and drop text file fileSystem.root.getFile( textFile.name, { create: true }, function (fileEntry) { fileEntry.createWriter( function (fileWriter) { fileWriter.onwriteend = function(e) { console.log("Write completed (" + textFile.name + ")"); fileSystem.root.getFile( textFile.name, {}, function (fileEntry) { fileEntry.file( function (file) { dropFile(file); }, fileErrorHandler ); }, fileErrorHandler ); }; fileWriter.onerror = function(e) { console.log("Write failed (" + textFile.name + "): " + e.toString()); }; fileWriter.write(new Blob([ textFile.content ], { type: textFile.contentType })); }, fileErrorHandler ); }, fileErrorHandler ); // Create and drop image file fileSystem.root.getFile( imageFile.name, { create: true }, function (fileEntry) { fileEntry.createWriter( function (fileWriter) { fileWriter.onwriteend = function(e) { console.log("Write completed (" + imageFile.name + ")"); fileSystem.root.getFile( imageFile.name, {}, function (fileEntry) { fileEntry.file( function (file) { dropFile(file); }, fileErrorHandler ); }, fileErrorHandler ); }; fileWriter.onerror = function(e) { console.log("Write failed (" + imageFile.name + "): " + e.toString()); }; fileWriter.write(new Blob(imageFile.contentBytes(), { type: imageFile.contentType })); }, fileErrorHandler ); }, fileErrorHandler ); }, fileErrorHandler ); })(); 

O conteúdo do arquivo de texto gerado automaticamente é fornecido como uma string e o conteúdo do arquivo de imagem é fornecido como uma string codificada em base64. Estes são fáceis de mudar. Por exemplo, o arquivo de texto de teste pode conter não apenas texto simples, mas também HTML. Nesse caso, não se esqueça de alterar o campo textFile.contentType de text/plain para text/html e de include esse tipo de conteúdo na matriz acceptedTypes e na function previewfile . A imagem de teste também pode ser alterada facilmente, você só precisa de um conversor image-to-base64 .

Eu tive que estender o código do manipulador de queda para lidar com arquivos de texto, além de imagens:

 acceptedTypes = { 'text/plain': true, // <-- I added this 'image/png': true, 'image/jpeg': true, 'image/gif': true }, ... function previewfile(file) { if (tests.filereader === true && acceptedTypes[file.type] === true) { var reader = new FileReader(); if (file.type === 'text/plain') { // <-- I added this branch reader.onload = function (event) { var p = document.createElement("p"); p.innerText = event.target.result; holder.appendChild(p); } reader.readAsText(file); } else { reader.onload = function (event) { var image = new Image(); image.src = event.target.result; image.width = 250; // a fake resize holder.appendChild(image); }; reader.readAsDataURL(file); } } else { holder.innerHTML += '

Uploaded ' + file.name + ', ' + file.size + ' B, ' + file.type; console.log(file); } }

Note que depois de carregar o jsfiddle , os arquivos autogerados podem ser listados para fins de debugging:

Sistema de arquivos temporários

Resultado

Resultado

A captura de canvas mostra que a queda simulada inseriu o conteúdo do arquivo de texto gerado automaticamente antes da imagem gerada automaticamente. O código HTML do alvo DND

parece com isto:

 

hello, world

@kol resposta é uma boa maneira de se livrar do evento arrastar e soltar, mas ainda tenho que selecionar manualmente um arquivo do meu computador. Este é o bit que eu estou interessado em simular. Existe uma maneira de criar uma variável de arquivo programaticamente? -caiocpricci2

Tente isso

 function createFile() { var create = ["
file
"]; var blob = new Blob([create], {"type" : "text/html"}); return ( blob.size > 0 ? blob : "file creation error" ) }; createFile()