私は、ユーザーが画像をアップロードできるようにするアプリケーション(Node.jsで、この場合は関係ありません)に取り組んでいます。入力(type = "file")フィールドを持つフォームを使用すると正常に機能します。
ただし、代わりにHTML5のドラッグアンドドロップを使用して画像をアップロードできるようにしたいのです。私が来た限り、画像をクライアントにドラッグすることは可能であり、画像のサムネイルはdivに表示されます。ただし、ファイルのアップロードを機能させるには、本当に助けが必要です。
重要なのは、現在使用しているフォームを使用し、(どういうわけか)ファイルのパスを入力フィールドに渡すことです。つまり、フローは現在とまったく同じように機能しますが、参照してファイルを選択する代わりにドラッグアンドドロップで入力フィールドに添付したい。
以下のドラッグアンドドロップ用のjsコードでは、クライアントにドラッグされたファイルは変数「file」に格納されており、「file.name」、「file.type」、「file.size」を使用できます。以前からフォームで機能するのとまったく同じ方法です。ただし、ファイル「パス」(file.path)にアクセスできないため、以前と同じようにファイルサーバー側にアクセスしてアップロードすることができません。
問題は、ファイルがクライアントにドラッグされた後、ファイルオブジェクトを入力フィールドに渡して、[送信]をクリックしてファイルをアップロードできるようにすることは可能ですか?もしそうなら、これはどのように行うことができますか?
前もって感謝します!
ドロップボックスとファイルのアップロードに使用しているフォーム:
<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;
};
},
ファイル入力を使用してファイルデータを追加することはできません。それでも、(他の技術の中でも)できることは、base64(reader.onloadイベントから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ファイル入力を削除することもできます。
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を管理者として実行していないためドラッグアンドドロップが無効になります!)、reader.onload()関数にブレークポイントを設定すると、非表示フィールドDroppedFileContentにエンコードされたファイルコンテンツが含まれますが、 btnDrop_Clickからアクセスします。reader.onload()の前に設定された「テスト」のみが含まれ、エンコードされたファイルの内容は含まれません。 DroppedFileNam.Valueフィールドは、Javascriptで設定されたとおりです。
セキュリティ上の理由から、フィールドのパスを知ることは不可能です。ドラッグアンドドロップでは、メインフォームとは別にアップロードする必要があります。例については、こちらをご覧ください: http://www.sitepoint.com/html5-file-drag-and-drop/