Передача пути к загруженному файлу из HTML5 drag & drop в поле ввода
Я работаю над приложением (в Node.js, что не имеет отношения к этому случаю), что позволяет пользователю загружать изображение. Он отлично работает с использованием формы с полем ввода (type="file").
Однако, я хочу, чтобы вы могли загружать изображение, используя вместо этого перетаскивание HTML5. Насколько я понял, можно перетащить изображение клиенту, а миниатюра изображения отображается в div. Однако мне действительно нужна помощь в том, чтобы загрузить файл.
Дело в том, что я хочу использовать форму, которую я использую прямо сейчас, и (каким-то образом) передать путь файла к полю ввода, то есть поток будет работать точно так же, как сейчас, но вместо того, чтобы выбирать файл, просматривая его. Я хочу привязать его к полю ввода путем перетаскивания.
В приведенном ниже js-коде для перетаскивания файл, перетаскиваемый клиенту, хранится в переменной "файл", и я могу использовать "file.name", "file.type" и "file.size" точно так же, как и раньше, с формой. Однако я не могу получить доступ к файлам "путь" (file.path), который делает невозможным доступ к стороне файлового сервера для загрузки так же, как я делаю это с тех пор.
Вопрос в том, можно ли передать объект файла в поле ввода после того, как файл был перенесен на клиент, чтобы я мог нажать "отправить" и загрузить файл? Если да, как это можно сделать?
Спасибо заранее!
dropbox, а также форму, которую я использую для загрузки файлов:
<div id='upload'>
<article>
<div id='holder'>
<p id='status'>File API and FileReader API not supported</p>
</div>
</article>
<form method='post' enctype='multipart/form-data' action='/file-upload'>
<p>
<input type='file' name='thumbnail'>
</p>
<p>
<input type='submit'>
</p>
</form>
</div>
код для перетаскивания:
uploadImage: function(){
var holder = document.getElementById('holder'),
state = document.getElementById('status');
if (typeof window.FileReader === 'undefined') {
state.className = 'fail';
} else {
state.className = 'success';
state.innerHTML = 'File API & FileReader available';
}
holder.ondragover = function () { this.className = 'hover'; return false; };
holder.ondragend = function () { this.className = ''; return false; };
holder.ondrop = function (e) {
this.className = '';
e.preventDefault();
var file = e.dataTransfer.files[0],
reader = new FileReader();
reader.onload = function (event) {
holder.style.background = 'url(' + event.target.result + ') no-repeat center';
};
reader.readAsDataURL(file);
return false;
};
},
Ответы
Ответ 1
Вы не можете использовать ввод файла для добавления данных файла.
Тем не менее, что вы можете сделать (среди других техник) - использовать base64 (изначально доступный через reader.onload event как event.target.result при использовании метода readAsDataURL) закодированные данные и помещать их в скрытое поле:
HTML
<article>
<div id='holder'>
<p id='status'>File API and FileReader API not supported</p>
</div>
</article>
<form method='post' enctype='multipart/form-data' action='/file-upload'>
<input type='file' name='thumbnail' />
<input type='hidden' name='base64data' />
<input type='submit' formenctype='application/x-www-form-urlencoded' />
</form>
JS
reader = new FileReader();
reader.onload = function (event) {
document.getElementById('base64data').setAttribute('value', event.target.result);
};
reader.readAsDataURL(file);
Со стороны сервера вы сможете получить кодированные данные base64 из файла, просто расшифруйте его и используйте, как хотите.
При отправке формы вы также можете изменить атрибут "enctype" (сделанный с помощью атрибута formenctype) и удалить основной вход файла html, поскольку данные будут помещены в текстовое поле.
Ответ 2
Невозможно узнать путь поля для целей безопасности. При перетаскивании вы должны загрузить его независимо от основной формы. Вот пример: http://www.sitepoint.com/html5-file-drag-and-drop/
Ответ 3
Я обнаружил, что скрытое поле, установленное в reader.onload (см. ответ по @challet), не устанавливается при обращении в коде позади. Я использую asp.net и проект WebForms. Чтобы получить доступ к скрытым полям, я должен добавить MainContent_ к именам полей. код aspx ниже
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
...
<script type="text/javascript">
function dropHandler(ev) {
alert("File(s) dropped");
// Prevent default behavior (Prevent file from being opened)
ev.preventDefault();
//alert("Default prevented");
if (ev.dataTransfer.items) {
if (ev.dataTransfer.items.length > 1) {
alert("Only single files can be dragged and dropped into Caption Pro Web");
return;
}
// If dropped items aren't files, reject them
if (ev.dataTransfer.items[0].kind === 'file') {
var file = ev.dataTransfer.items[0].getAsFile();
document.getElementById("MainContent_DroppedFileName").value = ev.dataTransfer.items[0].name
reader = new FileReader();
reader.onload = function (event) {
document.getElementById('MainContent_DroppedFileContent').value = event.target.result;
};
reader.readAsDataURL(ev.dataTransfer.items[0]);
}
} else {
// Use DataTransfer interface to access the file(s)
if (ev.dataTransfer.files.length > 1) {
alert("Only single files can be dragged and dropped into Caption Pro Web");
return;
}
document.getElementById("MainContent_DroppedFileName").value = ev.dataTransfer.files[0].name
document.getElementById("MainContent_DroppedFileContent").value = "Test";
reader = new FileReader();
reader.onload = function (event) {
document.getElementById("MainContent_DroppedFileContent").value = event.target.result;
};
reader.readAsDataURL(ev.dataTransfer.files[0]);
}
document.getElementById('<%=btnDrop.ClientID %>').click();
}
</script>
...
<div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
<p>Drag image to this Drop Zone ...</p>
</div>
<asp:HiddenField ID="DroppedFileName" runat="server" />
<asp:HiddenField ID="DroppedFileContent" runat="server" />
...
</asp:Content>
Я получаю доступ к скрытым полям из c #, как показано ниже
protected void btnDrop_Click(object sender, EventArgs e)
{
string FileName = DroppedFileName.Value;
string FileContent = DroppedFileContent.Value;
}
Если я использую Internet Explorer в качестве целевого браузера (не запускаю VS как Admin, так как это отключает перетаскивание!) и устанавливаю точку останова в функции reader.onload(), скрытое поле DroppedFileContent содержит содержимое закодированного файла, но когда Я пытаюсь получить к нему доступ из btnDrop_Click, он содержит только "Test", как установлено до reader.onload(), и не содержит зашифрованного содержимого файла. Поле DroppedFileNam.Value является таким, как установлено в Javascript.