File API紹介の最終回となる今回は、
FileTransferオブジェクトを使ったファイルダウンロード・アップロード
FileTransferオブジェクトを使用して、
新たに登場するオブジェクトとメソッドは次のとおりです。
- FileTransferオブジェクト
- FileTransferErrorオブジェクト
- FileUploadOptionsオブジェクト
- FileUploadResultオブジェクト
- downloadメソッド
- uploadメソッド
FileTransfer/FileTransferError/FileUploadOptions/ FileUploadResultオブジェクトとは
選択したファイルを外部サーバに送信するサンプルプログラムを紹介する前に、
FileTransferオブジェクトは、
FileTransferオブジェクトにプロパティはありません。用意されているメソッドは次のとおりです
メソッド名 | 内容 |
---|---|
使い方 | |
download | 指定したサーバからファイルをダウンロードします。
|
fileTransfer. | |
upload | 指定したサーバにファイルをアップロードします。
|
fileTransfer. |
FileTransferErrorオブジェクトは、
FileTransferErrorオブジェクトのプロパティは次のとおりです。
- code
- 対応するエラーコードを返します
- source
- ソースのURIを返します
- target
- ターゲットのURIを返します
- http_
status - HTTPステータスコードを返します
(レスポンスコードがHTTP接続から返されたときのみ有効です)
対応する定数とエラーコードは次のとおりです。
- FileTransferError.
FILE_ NOT_ FOUND_ ERR - ダウンロード時の第2引数に指定したパスがファイルURLでない場合や、
アップロード時の第1引数に指定したファイルが見つからない場合に返ります - FileTransferError.
INVALID_ URL_ ERR - ダウンロード時・
アップロード時ともに第2引数に不正なファイルURLを指定した場合に返ります - FileTransferError.
CONNECTION_ ERR - ネットワーク接続がない場合や、
処理完了時のレスポンスコードが200~300の範囲でなかった場合に返ります
// cordova-2.0.0.js 2578-2580
FileTransferError.FILE_NOT_FOUND_ERR = 1;
FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
// CDVFileTransfer.h 24-28
enum CDVFileTransferError {
FILE_NOT_FOUND_ERR = 1,
INVALID_URL_ERR = 2,
CONNECTION_ERR = 3
};
// CDVFileTransfer.m 80-103
// ファイルアップロード実装の一部
if (!url) {
errorCode = INVALID_URL_ERR;
NSLog(@"File Transfer Error: Invalid server URL %@", server);
} else if(![file isFileURL]) {
errorCode = FILE_NOT_FOUND_ERR;
NSLog(@"File Transfer Error: Invalid file path or URL %@", filePath);
} else {
// check that file is valid
NSFileManager* fileMgr = [[NSFileManager alloc] init];
BOOL bIsDirectory = NO;
BOOL bExists = [fileMgr fileExistsAtPath:[file path] isDirectory:&bIsDirectory];
if (!bExists || bIsDirectory) {
errorCode = FILE_NOT_FOUND_ERR;
} else {
// file exists, make sure we can get the data
fileData = [NSData dataWithContentsOfURL:file];
if(!fileData) {
errorCode = FILE_NOT_FOUND_ERR;
NSLog(@"File Transfer Error: Could not read file data %@", filePath);
}
}
[fileMgr release];
}
// CDVFileTransfer.m 224-230
// ファイルダウンロード実装の一部
if (!url) {
errorCode = INVALID_URL_ERR;
NSLog(@"File Transfer Error: Invalid server URL %@", sourceUrl);
} else if(![file isFileURL]) {
errorCode = FILE_NOT_FOUND_ERR;
NSLog(@"File Transfer Error: Invalid file path or URL %@", filePath);
}
FileTransferオブジェクトのcodeプロパティと、
FileUploadOptionsは、
FileUploadOptionsのプロパティは次のとおりです。
- fileKey
- Content-Dispositionヘッダのname属性に指定する名前を指定します。デフォルト値はnullです
- fileName
- Content-Dispositionヘッダのfilename属性に指定する名前を指定します。デフォルト値はnullです
- mimeType
- Content-Typeヘッダに指定するMIMEタイプを指定します。デフォルト値はnullです。指定しなかった場合、
Content-Typeヘッダは送信されません - params
- HTTPリクエストに含めたいデータをkey/
value形式で指定します - chunkedMode
- チャンク・
ストリーミングでファイルを送信したい場合はtrueを指定します (執筆時点で、 この指定は無視される模様です)


FileUploadResultオブジェクトは、
FileUploadResultオブジェクトのプロパティは次のとおりです。
- bytesSent
- 送信されたバイト数を示します
- responseCode
- サーバから返されたHTTPレスポンスコードを示します
- response
- サーバから返されたHTTPレスポンスを示します
iOSの場合、
また、
ダウンロード・
ファイル転送に関係するオブジェクトをまとめると、
オブジェクト名 | 内容 |
---|---|
FileTransfer | ファイルのダウンロード・
|
FileTransferError | FileTransferオブジェクトのdownload/ |
FileUploadOptions | FileTransferオブジェクトのuploadメソッド使用時、 |
FileUploadResult | FileTransferオブジェクトのuploadメソッド使用時、 |
ファイルのダウンロード・アップロード(iOS/Android)
ファイルのダウンロード・
- ダウンロードするファイルは、
gihyo. jpのロゴ 。PERSISTENTファイルシステムに保存 - PERSISTENTファイルシステムからファイルを選択し、
アップロード - アップロード先には、
ファイルを受信してカレントディレクトリに保存するプログラムを指定する。PHPで実装
1: <!DOCTYPE html>
2: <html>
3: <head>
4: <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5: <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
6: <title>File API Test (6)</title>
7: </head>
8: <body>
9: <div class="app">
10: <h1>File API Test</h1>
11: <p>
12: <input id="download" type="button" value="download gihyo logo">
13: </p>
14: <ul id="fileList"></ul>
15: </div>
16: <script type="text/javascript" src="cordova-2.0.0.js"></script>
17: <script type="text/javascript">
18: var directoryEntry;
19:
20: document.addEventListener('deviceready', init, false);
21: function init() {
22: window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getFilesFromDirectory, fail);
23: document.getElementById('download').addEventListener('click', downloadFile, false);
24: }
25:
26: function getFilesFromDirectory(fileSystem) {
27: directoryEntry = fileSystem.root;
28: var directoryReader = directoryEntry.createReader();
29: directoryReader.readEntries(putFileName, fail);
30: }
31:
32: function putFileName(entries) {
33: for ( index = 0; index < entries.length; index++ ) {
34: if ( entries[index].isFile ) {
35: var listItem = document.createElement('li');
36: listItem.textContent = entries[index].name;
37: listItem.title = entries[index].fullPath;
38: listItem.addEventListener('click', uploadFile, false);
39: document.getElementById('fileList').appendChild(listItem);
40: }
41: }
42: }
43:
44: function downloadFile() {
45: // FileTransferオブジェクトを作成
46: var fileTransfer = new FileTransfer();
47:
48: // ダウンロード先のURIをencodeURIでエンコード
49: var uri = encodeURI('http://image.gihyo.co.jp/assets/templates/gihyojp2007/image/gihyojp_logo.png');
50:
51: // 保存するファイルの名前
52: var fileName = 'gihyojp_logo.png';
53:
54: // 保存先をフルパスで指定
55: var path = directoryEntry.fullPath + '/' + fileName ;
56:
57: // ファイルのダウンロードを実行
58: fileTransfer.download(uri, path, downloadSuccess, downloadFail);
59: }
60:
61: function downloadSuccess(fileEntry) {
62: alert('ファイルを' + fileEntry.fullPath + 'に保存しました。');
63: location.reload();
64: }
65:
66: function downloadFail(fileTransferError) {
67: var error = '';
68:
69: switch(fileTransferError.code) {
70: case FileTransferError.FILE_NOT_FOUND_ERR:
71: error = '第2引数にファイルURLが指定されていません';
72: break;
73: case FileTransferError.INVALID_URL_ERR:
74: error = '不正なファイルパスが第2引数で指定されています';
75: break;
76: case FileTransferError.CONNECTION_ERR:
77: error = '接続エラー';
78: break;
79: default:
80: error = '未定義のエラー';
81: break;
82: }
83:
84: alert(error + '\nhttp_status: ' + fileTransferError.http_status);
85: }
86:
87: function uploadFile(event) {
88: // FileTransferオブジェクトを作成
89: var fileTransfer = new FileTransfer();
90:
91: // アップロード先URIをencodeURIでエンコード
92: var uri = encodeURI('http://(ホスト名)/receive.php');
93:
94: // FileUploadOptionsオブジェクトを作成し、送信時の情報を指定
95: var uploadOptions = new FileUploadOptions();
96: uploadOptions.fileKey = 'file';
97: uploadOptions.fileName = event.target.textContent;
98:
99: // ファイルのアップロードを実行
100: fileTransfer.upload(event.target.title, uri, uploadSuccess, uploadFail, uploadOptions);
101: }
102:
103: function uploadSuccess(uploadResult) {
104: var result;
105:
106: // アップロード先(receive.php)から返るJSONをパース
107: if ( 'Android' === device.platform ) {
108: result = JSON.parse(uploadResult.response);
109: } else {
110: // iOSの場合はエンコードされた文字列になるため、decodeURIでデコード
111: result = JSON.parse(decodeURI(uploadResult.response));
112: }
113:
114: if ( 0 === result.errorCode ) {
115: alert('ファイルのアップロードに成功しました\nbytesSent: ' + uploadResult.bytesSent + '\nresponseCode: ' + uploadResult.responseCode);
116: } else {
117: alert('ファイルのアップロードに失敗しました\n' + result.message + '\nbytesSent: ' + uploadResult.bytesSent + '\nresponseCode: ' + uploadResult.responseCode);
118: }
119: }
120:
121: function uploadFail(fileTransferError) {
122: var error = '';
123:
124: switch(fileTransferError.code) {
125: case FileTransferError.FILE_NOT_FOUND_ERR:
126: error = '第1引数に指定したファイルが見つかりません';
127: break;
128: case FileTransferError.INVALID_URL_ERR:
129: error = '不正なURIが第2引数で指定されています';
130: break;
131: case FileTransferError.CONNECTION_ERR:
132: error = '接続エラー';
133: break;
134: default:
135: error = '未定義のエラー';
136: break;
137: }
138:
139: alert(error + '\nhttp_status: ' + fileTransferError.http_status);
140: }
141:
142: function fail(error) {
143: alert('エラーが発生しました。エラーコード: ' + error.code);
144: }
145: </script>
146: </body>
147: </html>
<?php
// ファイルを受信し、JSONで結果を出力
// { errorCode : (エラーコード) , message : (メッセージ) }
// 定義したエラーコードは次のとおり
// -1: ファイルがアップロードされていない
// 0 : エラーなし
// 1 : move_uploaded_fileに失敗
// 2 : ファイル名の制限により失敗
// ファイルがアップロードされているか
if (!is_uploaded_file($_FILES['file']['tmp_name'])) {
echo json_encode(array('errorCode' => -1, 'message' => 'ファイルがアップロードされていません'));
exit;
}
// 拡張子が jpg, png, txt のみのファイルを受け付ける
if ( !preg_match('/\.jpg$|\.png$|\.txt$/i', $_FILES['file']['name']) ) {
echo json_encode(array('errorCode' => 2, 'message' => '受信できるファイルの拡張子はjpg/png/txtの3種類のみです'));
exit;
}
// アップロードされたファイルを、カレントディレクトリに移動
if (move_uploaded_file($_FILES['file']['tmp_name'], './' . str_replace('/', '', $_FILES['file']['name']))) {
echo json_encode(array('errorCode' => 0, 'message' => 'エラーなし'));
exit;
}
// エラー処理
echo json_encode(array('errorCode' => 1, 'message' => 'move_upload_fileに失敗しました。パーミッションの設定を確認してください'));
exit;
?>
前述のとおり、
まずはiOSで実行してみましょう。アプリケーションを起動すると、

[download gihyo logo]ボタンをクリックすると、


列挙されているファイル名をクリックすると、


PHPではファイルを受信し、

存在しないサーバURLや、

続いて、




このサンプルコードでは、
- PERSISTENTファイルシステムに格納されているファイル一覧を表示
- [download gihyo logo]ボタンをクリックすると、
指定したURIから画像ファイルをダウンロードする - ファイル名をクリックすると、
そのファイルを指定したURIにアップロードする
まずはファイルのダウンロードを行っているコードから確認してみましょう。
44: function downloadFile() {
45: // FileTransferオブジェクトを作成
46: var fileTransfer = new FileTransfer();
47:
48: // ダウンロード先のURIをencodeURIでエンコード
49: var uri = encodeURI('http://image.gihyo.co.jp/assets/templates/gihyojp2007/image/gihyojp_logo.png');
50:
51: // 保存するファイルの名前
52: var fileName = 'gihyojp_logo.png';
53:
54: // 保存先をフルパスで指定
55: var path = directoryEntry.fullPath + '/' + fileName ;
56:
57: // ファイルのダウンロードを実行
58: fileTransfer.download(uri, path, downloadSuccess, downloadFail);
59: }
46行目でFileTransferオブジェクトをあたらしく作成します。ダウンロードしたいURIをencodeURIメソッドを使ってエンコードし、
58行目でファイルのダウンロードを行います。あらかじめ、
ダウンロードに成功した場合は、
61: function downloadSuccess(fileEntry) {
62: alert('ファイルを' + fileEntry.fullPath + 'に保存しました。');
63: location.reload();
64: }
fileEntryオブジェクトのfullPathプロパティに保存したファイルのフルパスが格納されていますので、
ダウンロードに失敗した場合は、
66: function downloadFail(fileTransferError) {
67: var error = '';
68:
69: switch(fileTransferError.code) {
70: case FileTransferError.FILE_NOT_FOUND_ERR:
71: error = '第2引数にファイルURLが指定されていません';
72: break;
73: case FileTransferError.INVALID_URL_ERR:
74: error = '不正なファイルパスが第2引数で指定されています';
75: break;
76: case FileTransferError.CONNECTION_ERR:
77: error = '接続エラー';
78: break;
79: default:
80: error = '未定義のエラー';
81: break;
82: }
83:
84: alert(error + '\nhttp_status: ' + fileTransferError.http_status);
85: }
続いてアップロードを行っているコードを確認してみましょう。
87: function uploadFile(event) {
88: // FileTransferオブジェクトを作成
89: var fileTransfer = new FileTransfer();
90:
91: // アップロード先URIをencodeURIでエンコード
92: var uri = encodeURI('http://(ホスト名)/receive.php');
93:
94: // FileUploadOptionsオブジェクトを作成し、送信時の情報を指定
95: var uploadOptions = new FileUploadOptions();
96: uploadOptions.fileKey = 'file';
97: uploadOptions.fileName = event.target.textContent;
98:
99: // ファイルのアップロードを実行
100: fileTransfer.upload(event.target.title, uri, uploadSuccess, uploadFail, uploadOptions);
101: }
FileTransferオブジェクトを作成し、
たとえばファイル一覧においてgihyojp_
Content-Disposition: form-data; name="file"; filename="gihyojp_logo.png"
100行目でファイルのアップロードを行います。アップロード先のホストは、
アップロードに成功した場合は、
103: function uploadSuccess(uploadResult) {
104: var result;
105:
106: // アップロード先(receive.php)から返るJSONをパース
107: if ( 'Android' === device.platform ) {
108: result = JSON.parse(uploadResult.response);
109: } else {
110: // iOSの場合はエンコードされた文字列になるため、decodeURIでデコード
111: result = JSON.parse(decodeURI(uploadResult.response));
112: }
113:
114: if ( 0 === result.errorCode ) {
115: alert('ファイルのアップロードに成功しました\nbytesSent: ' + uploadResult.bytesSent + '\nresponseCode: ' + uploadResult.responseCode);
116: } else {
117: alert('ファイルのアップロードに失敗しました\n' + result.message + '\nbytesSent: ' + uploadResult.bytesSent + '\nresponseCode: ' + uploadResult.responseCode);
118: }
119: }
receive.
繰り返しになりますが、iOSの場合、
JSONで渡されたエラーコードを読み取り、
アップロードに失敗した場合は、
121: function uploadFail(fileTransferError) {
122: var error = '';
123:
124: switch(fileTransferError.code) {
125: case FileTransferError.FILE_NOT_FOUND_ERR:
126: error = '第1引数に指定したファイルが見つかりません';
127: break;
128: case FileTransferError.INVALID_URL_ERR:
129: error = '不正なURIが第2引数で指定されています';
130: break;
131: case FileTransferError.CONNECTION_ERR:
132: error = '接続エラー';
133: break;
134: default:
135: error = '未定義のエラー';
136: break;
137: }
138:
139: alert(error + '\nhttp_status: ' + fileTransferError.http_status);
140: }
FileTransferErrorオブジェクトのエラー内容ついて、
また、
以上、
メソッドの返り値や挙動など、