よくある Webページ上に ファイル を ドラッグ & ドロップ して アップロード する アプリ を作ってみます。 この記事では サーバー側 と クライアント側 をまとめて掲載しています。 サーバー側は ASP.NET WebAPI、クライアント側は HTML + JavaScript で実装します。 アップロード は POST で フォームデータ として アップロード します。
目次
サンプルコード
サーバー処理
WebAPI 用 の コントローラ を作成します。 受け取る ファイルデータ は フォームデータ として受け取ります。 同じファイル名をアップロードするとエラーになる点にご注意ください。。
FileController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Web.Http; public class FileController : ApiController { // POST api/<controller> public async Task<httpresponsemessage> Post( bool overwrite = false ) { var tempPath = Path.GetTempPath(); var provider = new MultipartFormDataStreamProvider(tempPath); await this .Request.Content.ReadAsMultipartAsync(provider); foreach (var file in provider.FileData) { // アップロードファイル名の取得 var fileName = file.Headers.ContentDisposition.FileName; fileName = fileName.StartsWith( "\"" ) || fileName.StartsWith( "'" ) ? fileName.Substring(1, fileName.Length - 1) : fileName; fileName = fileName.EndsWith( "\"" ) || fileName.EndsWith( "'" ) ? fileName.Substring(0, fileName.Length - 1) : fileName; fileName = Path.GetFileName(fileName); // ファイルの移動 File.Move(file.LocalFileName, Path.Combine( "D:\\" , fileName)); } return this .Request.CreateResponse(HttpStatusCode.OK); } } </httpresponsemessage> |
クライアント処理
記述する部分としては HTML、CSS、JavaScript があるので、それぞれ順に説明していきます。
HTML
まずは html について。 ファイルアップロード に関して html で気にするとすれば ドラッグ&ドロップ をどの領域で受け付けるか、と言ったところでしょうか。 今回は ブラウザページ全体 (body) で受け付けるようにしたいと思います。
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <!DOCTYPE html> < html > < head > < meta charset = "utf-8" /> < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title >Index - My ASP.NET Application</ title > < link href = "/Content/Site.css" rel = "stylesheet" type = "text/css" /> < link href = "/Content/bootstrap.min.css" rel = "stylesheet" type = "text/css" /> < script src = "/Scripts/library/modernizr-2.6.2.js" ></ script > </ head > < body > < div class = "navbar navbar-inverse navbar-fixed-top" > < div class = "container" > < div class = "navbar-header" > < button type = "button" class = "navbar-toggle" data-toggle = "collapse" data-target = ".navbar-collapse" > < span class = "icon-bar" ></ span > < span class = "icon-bar" ></ span > < span class = "icon-bar" ></ span > </ button > < a class = "navbar-brand" href = "/" >Application name</ a > </ div > < div class = "navbar-collapse collapse" > < ul class = "nav navbar-nav" > </ ul > </ div > </ div > </ div > < div class = "container body-content" > < h2 >Index</ h2 > < div id = "msg" ></ div > < hr /> < footer > < p >© 2015 - My ASP.NET Application</ p > </ footer > </ div > < script src = "/Scripts/library/jquery-1.10.2.min.js" ></ script > < script src = "/Scripts/library/bootstrap.min.js" ></ script > < script type = "text/javascript" src = "/Scripts/Home/index.js" ></ script > </ body > </ html > |
CSS
ドラッグ & ドロップ の 領域 を 画面全体 としたい場合、 html と body に対して width: 100%; height: 100%; を指定します。 この指定をしておかないと、画面全体ではなく指定された領域のみでしかファイルアップロードが受け付けられません。 (意図的に場所指定したいのであれば問題ないですが…)
Site.css
1 2 3 4 | html, body { width : 100% ; height : 100% ; } |
JavaScript
Webページ に ファイル が ドラッグ&ドロップ で落とされたとき、ファイルを受け取ってサーバーへ投げつける処理を記載します。 ポイントはいくつかあるのですが…まずはサンプルコードを掲載して、サンプルコードのあとに解説を載せます。
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | /** * 指定されたファイルをアップロードします。 * @param {FileList} files アップロードするファイルリスト */ var upload = function (files) { var i, formData; // アップロード用のデータを生成 formData = new FormData(); for (i = files.length; i--;) { formData.append( 'files' , files[i]); } // ファイルアップロードの実行 $.ajax({ url: '/api/file?overwrite=true' , method: 'POST' , processData: false , contentType: false , data: formData }).done( function (data, textStatus, jqXHR) { $( '#msg' ).append(JSON.stringify(data)); }).fail( function (jqXHR, textStatus, errorThrown) { $( '#msg' ).append(textStatus); }); }; /** * 指定されたファイルを画面に表示する。 * @param {FileList} files 読み取るファイルリスト */ var read = function (files) { var fragment, i, item; fragment = document.createDocumentFragment(); for (i = files.length; i--;) { item = document.createElement( 'div' ); item.appendChild(document.createTextNode(files[i].name)); fragment.appendChild(item); } $( '#msg' ).append(fragment); }; /** * dragover イベント が発生したとき呼び出されます。 * @param {Event} event イベントオブジェクト */ var body_ondragover = function (event) { event.preventDefault(); $( '#msg' ).text( 'ondragover' ); }; /** * drop イベント が発生したとき呼び出されます。 * @param {Event} event イベントオブジェクト */ var body_ondrop = function (event) { var i, files, fragment, item; $( '#msg' ).text( 'ondrop' ); files = event.originalEvent.dataTransfer.files || []; read(files); upload(files); }; /** * ドキュメント生成が完了したとき呼び出されます。 */ var document_onready = function (event) { $(window.document.body).on( 'dragover' , body_ondragover ).on( 'drop' , body_ondrop ); }; $(document).ready(document_onready); |
ドラッグ & ドロップ イベント
ドラッグ&ドロップ 関連のイベントは以下の通りです。
このうち ファイルアップロード に関連するのは ondragover
と ondrop
。
- ondragstart
- ondrag
- ondragend
- ondragenter
- ondragover
- ondragleave
- ondrop
ファイルアップロードに関する ondragover
と ondrop
には以下のような処理を記述します。
- ondragover
- preventDefault で デフォルト機能を無効化
- ondrop
- 実際の ドロップ処理 を実装
ドロップされたファイル情報の取得
ファイルドロップ された際、File オブジェクト
を利用して ドロップ された ファイル情報 を取得します。
jQuery で File オブジェクト
へ アクセス するためには、以下のように オリジナル の イベントオブジェクト からたどるようにします。
1 | event.originalEvent.dataTransfer.files[i] |
File オブジェクト
には以下のようなプロパティ、メソッドがあるようです。
File オブジェクト
- プロパティ
lastModifiedDate
name
isClosed
size
type
- メソッド
close()
slice([start[, end[, contentType]]])
Ajax で ファイルアップロード
ファイルアップロードには File オブジェクト
から取得される情報を FormData オブジェクト
に詰め込んだものを 送信 します。
また、 jQuery を用いて送信する場合、 processData: false
と contentType: false
を指定します。
これらの指定をしておかないと、 jQuery が勝手にエスケープ処理をしてしまい、サーバー側で正しくデータを受け取れません。
参考記事
- w3schools.com - ondrop Event
- MDN - FileReader
- しばやん雑記 - ASP.NET Web API でアップロードされたファイルを扱う方法を知らなかったので調べた
- しばやん雑記 - HTML5 の Drag and Drop API と File API を使ってファイルアップロードを実装する
- CODE PROJECT - Web API Thoughts 1 of 3 - Data Streaming
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!