使ってみよう! Windows Live SDK/API

第49回SkyDrive API 概要(2)─⁠─ファイルのアップロードほか

アプリでSkyDriveのアクセス

SkyDrive APIの2回目です。前回はLive Connectを利用してSkyDriveのフォルダーとファイル情報の取得を紹介しました。今回はフォルダーの作成やファイルのアップロードなどの操作を行ってみましょう。これらの操作は待ち望んでいた人も多いのではないでしょうか。

以前に提供されていたAPIでは参照だけでしたが、Live Connectでは、制限はあるもののアプリからSkyDriveへのファイルアップロードなどより多くのアクセスが許可され、よりWindows Liveと統合したアプリ開発ができるようになっています。

ファイルのアップロード

さっそくAPIを利用してのSkyDriveへのファイルアップロードについてみてみましょう。アップロードは、HTTPのPOSTまたはPUTメソッドで行います。

アップロードを行うには、OAuthのスコープにwl.skydrive_updateを指定して、ユーザーからの認可を得る必要があります。Live ConnectでのOAuthについてはこれまでの内容を参照してください。

POSTメソッドによるアップロード

まず、POSTメソッドによるファイルのアップロードです。以下のようなフォルダーの内容を表すURLへファイルを送信します。SkyDrive直下のフォルダーのパスの場合は、/me/skydriveでした。/filesを付けてフォルダーの内容を表します。さらにOAuthのアクセストークンを付け、次のURLへファイルをPOSTメソッドで送信するとアップロードできます。

  • https://apis.live.net/v5.0/me/skydrive/files?access_token=ACCESS_TOKEN

実際にサーバーへ送信するHTTPの通信内容は、次のようなテキストです。

POST https://apis.live.net/v5.0/me/skydrive/files?access_token=ACCESS_TOKEN HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Content-Type: multipart/form-data; boundary=---------------------------7dc3801415811aa
Connection: Keep-Alive
Host: apis.live.net
Content-Length: 202

-----------------------------7dc3801415811aa
Content-Disposition: form-data; name="upfile"; filename="sample.txt"
Content-Type: text/plain

hogehoge
-----------------------------7dc3801415811aa--

サーバーからの応答は、ファイルの作成に成功した場合、次のようなJSON形式のデータです。作成されたファイルのidと一時的なファイルダウンロード用のURLが含まれています。

{
   "id": "file.xxxxx", 
   "source": "http://storage.live.com/xxxxx/sample.txt:Binary"
}

単純なHTTP POSTメソッドによる投稿ですので、簡単ですね。各種プログラミング言語で実装してみましょう。このあとPHPでのサンプルコードを示します。

アップロード先のフォルダーの指定は、前回紹介したFolderオブジェクトのidの値を使います。URLは以下のようになります。このURLは、FolderやFileオブジェクトのupload_locationの値と同等です。

  • https://apis.live.net/v5.0/FOLDER_ID/files

ファイルが同名の場合、通常は上書きされますが、クエリーにoverwriteパラメーターを付け、値にfalseを指定してアクセスすると、同名のときエラーメッセージを返すようにできます。

例:
https://apis.live.net/v5.0/me/skydrive/files?overwrite=false&access_token=ACCESS_TOKEN

アクセストークンはURLに含めるだけでなく、次のようにHTTPのAuthorizationヘッダーとしての指定も可能です。これはアップロードに限った話ではありません。

Authorization: Bearer ACCESS_TOKEN

PUTメソッドによるアップロード

PUTメソッドを使用した場合は、⁠me/skydrive/files/sample.txt」のようにファイル名をURLに付けてアクセスします。HTTPの通信で送信するデータは次のようになります。

PUT https://apis.live.net/v5.0/me/skydrive/files/sample.txt?access_token=ACCESS_TOKEN HTTP/1.1
Host: apis.live.net
Content-Length: 8
Connection: Keep-Alive

hogehoge

サーバーからの応答は、POSTメソッドのときと同じです。

既にSkyDrive上にあるファイルをPUTメソッドで上書きする場合は、Fileオブジェクトのidを使います。idを指定したパスだけでは、GETメソッドと同じ結果になり上書きされません。次のように/contentを付けてアクセスすると、既にあるファイルを上書きします。

  • https://apis.live.net/v5.0/FILE_ID/content?access_token=ACCESS_TOKEN

以上がファイルのアップロードの基本でした。ちなみに、アップロードしたファイルの共有状態は、アップロード先のフォルダーの共有の状態を継承するようです。公開されているフォルダーにアップロードすると、そのファイルも公開されている状態になります。また、ファイルの共有状態はAPIで変更できません。

PHPでファイルのアップロード

PHPでSkyDriveにファイルをアップロードするコードを書いてみましょう。特に難しいところはなく、単純なHTTPアクセスを行うプログラムです。アクセストークンを取得する部分は省略していますので、前回のコードと併せて確認してください。

ここではPOSTメソッドによるコードを示します。ファイルは、PHPの動いているWebサーバー上に一度アップロードしてから、Live ConnectでSkyDriveにアップロードします。

HTML部分は次のようにファイルをアップロードするフォームを用意します。また、エラーなどのメッセージを表示する領域も用意しておきます。

<form action="49.php" method="POST" enctype="multipart/form-data">
  <div>
    SkyDrive へファイルをアップロードします。<br />
    <input type="file" name="upfile" size="30" />
      <input type="submit" value="アップロード" />
  </div>
</form>
<div class="message"><?php echo $msg; ?></div>

次はPHPのコードです。ファイルがアップロードされた場合、一時的にファイルを保存して、SkyDriveへさらにアップロードします。アクセストークン(このコードでは$tokenに格納されているものとします)を得られている場合にのみ、以下の処理を実行するようにします。

if (is_uploaded_file($_FILES["upfile"]["tmp_name"])) {
  // 一時保存ディレクトリ
  $dir = "./tmp/";

  // ファイル名を新しく付ける
  $tmp = $_FILES["upfile"]["name"];
  $file = uniqid('', true) . substr($tmp, strrpos($tmp, '.'));

  if (move_uploaded_file($_FILES["upfile"]["tmp_name"], $dir . $file)) {
      // アップロードされたファイルを一時保存先へ移動し、成功した場合

      // SkyDrive へアップロード
      $res = upload_to_skydrive($token, $dir . $file);
      if ($res === false) {
          $msg = "Error";
      } else if (array_key_exists('error', $res)) {
          // エラーメッセージが返ってきた場合
          $msg = htmlspecialchars($res['error']['message'], ENT_QUOTES, 'UTF-8');
      } else {
          // アップロード成功が成功した場合
          $msg = 'アップロード完了: <a href="' . $res['source'] . '">' . htmlspecialchars($file, ENT_QUOTES, 'UTF-8') . '</a>';
      }

      // 一時ファイル削除
      @unlink($dir . $file);
  } else {
      $msg = 'アップロード失敗';
  }
}

上記コードで呼び出しているupload_to_skydrive関数は、次のようになります。関数には、アクセストークンと一時的に保存したファイルのパスを渡します。主な処理内容は、ファイルをPOSTメソッドで送信しているだけです。

function upload_to_skydrive($token, $file) {
    $url = 'https://apis.live.net/v5.0/me/skydrive/files';
    $data = array("file" => "@" . realpath($file));
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer $token"));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // (サーバー証明書を検証しない)
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    
    // エラーの場合 false を返す
    $res = curl_exec($ch);
    if ($no = curl_errno($ch)) {
        echo $no;
        return false;
    }
    curl_close($ch);
    return json_decode($res, true);
}

このコードでは、SkyDrive直下にのみアップロードを行います。アクセスするURLにFolderオブジェクトのidを指定するように変更すれば、指定したフォルダーにアップロードできるようになります。

サンプルでは、前回のOAuth部分のコードと組み合わせたコードを公開しています。

フォルダーの作成

次は、フォルダーを作ってみましょう。フォルダーを作成するには、フォルダー名を次のようなJSONデータで表し、フォルダーを示すURLへHTTP POSTメソッドで送信します。

{
    name: "新しいフォルダー"
}

作成に成功すると、Folderオブジェクトが返ってきます。既にある場合はエラーメッセージが返ります。

HTTPの通信内容は次のようになります。

POST https://apis.live.net/v5.0/me/skydrive?access_token=ACCESS_TOKEN HTTP/1.1
Content-Type: application/json
Host: apis.live.net
Content-Length: 34
Connection: Keep-Alive

{name: "新しいフォルダー"}

JSONのため、Content-Typeは「application/json」を指定します。

PHPで記述した場合は、次のように書けます。

$res = create_folder($token, 'me/skydrive', '新しいフォルダー');

function create_folder($token, $path, $name) {
    $url = 'https://apis.live.net/v5.0/' . $path;
    $data = '{name: "' . $name . '"}';

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, 
        array("Authorization: Bearer $token", 
              "Content-Type: application/json"));

    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    
    $res = curl_exec($ch);
    if ($no = curl_errno($ch)) {
        return false;
    }
    curl_close($ch);
    echo $res;
    return json_decode($res, true);
}

フォルダーの作成も簡単ですね。

フォルダー・ファイル情報の変更

続いて、フォルダーまたはファイルの情報の変更についてです。APIでは、名前と説明のみ変更できます。名前と説明は、FolderFileオブジェクトのnamedescriptionにあたります。

情報の変更は、HTTP PUTメソッドを使用します。変更したい内容のJSONデータを次のように指定し、フォルダーまたはファイルを示すURLへアクセスします。nameとdescriptionはどちらかひとつでも構いません。

{
    name: "新しいフォルダー名",
    description: "ほむほむ"
}

HTTPの通信内容は次のようになります。

PUT https://apis.live.net/v5.0/folder.xxxxx?access_token=ACCESS_TOKEN HTTP/1.1
Content-Type: application/json
Host: apis.live.net
Content-Length: 66
Connection: Keep-Alive

{name: "新しいフォルダー名", description: "ほむほむ"}

PHPでは次のように記述できます。

$res = update($token, 'file.xxxxx', '新しいフォルダー名', "ほむほむ");

function update($token, $path, $name, $desc) {
    $data = '{name: "' . $name . '", description: "' . $desc . '"}';
    $url = 'https://apis.live.net/v5.0/' . $path;
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, 
        array("Authorization: Bearer $token", 
              "Content-Type: application/json"));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    $res = curl_exec($ch);
    if ($no = curl_errno($ch)) {
        return false;
    }
    curl_close($ch);
    echo $res;
    return json_decode($res, true);
}

フォルダーの説明(description)は、SkyDriveで図1のように表示されます。

図1 フォルダー名の変更
図1 フォルダー名の変更

前回に紹介したとおりLive ConnectでSkyDriveにアップロードできるファイルの種類は文書や写真など限定されています。ファイル名をサポートしていない拡張子のものへ変更しようとすると、エラーメッセージが返ります。

フォルダー・ファイルの削除

次は、フォルダーまたはファイルの削除です。フォルダー・ファイルを示すURLにHTTP DELETEメソッドでアクセスすると削除できます。HTTPの通信内容は次のようになります。

DELETE https://apis.live.net/v5.0/file.xxxxx?access_token=ACCESS_TOKEN HTTP/1.1
Host: apis.live.net
Connection: Keep-Alive

PHPでは次のように記述できます。

$res = delete_file($token, 'file.xxxxx');

function delete_file($token, $path) {
    $url = 'https://apis.live.net/v5.0/' . $path;
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer $token"));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    
    $res = curl_exec($ch);
    if ($no = curl_errno($ch)) {
        return false;
    }
    curl_close($ch);
    echo $res;
    return json_decode($res, true);
}

SkyDriveは、普通にサービスを使用していてもそうですが、一度削除したフォルダーやファイルを元に戻せません。フォルダーを削除すると、そのフォルダーに含まれるすべてのフォルダーやファイルが削除されます。削除する場合は、気を付けて行いましょう。

フォルダー・ファイルの移動、ファイルのコピー

フォルダーとファイルの移動や、ファイルのコピーにもAPIは対応しています。移動とコピーは、あまり使う機会のないHTTP MOVEメソッドとCOPYメソッドで行います。

移動(またはコピー)先のフォルダーを次のようにJSONデータで指定します。移動の場合は、対象のフォルダーまたはファイルを示すURLに、コピーの場合は、対象のファイルを示すURLにアクセスします。

{
    destination: "folder.xxxxx"
}

移動の場合のHTTPの通信内容は次のようになります。

MOVE https://apis.live.net/v5.0/file.xxxxx?access_token=ACCESS_TOKEN HTTP/1.1
Content-Type: application/json
Host: apis.live.net
Content-Length: 60
Connection: Keep-Alive

{destination: "folder.xxxxx"}

コピーの場合、新しいFileオブジェクトの内容が返ってきます。

PHPでは次のように記述できます。

$res = move($token, 'file.xxxxx', 'folder.xxxxx');

function move($token, $src, $dest) {
    $data = '{destination: "' . $dest . '"}';
    
    $url = 'https://apis.live.net/v5.0/' . $src;
    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, 
        array("Authorization: Bearer $token", 
              "Content-Type: application/json"));
    
    // (コピーの場合は MOVE を COPY に変更するとできます)
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'MOVE');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

    $res = curl_exec($ch);
    if ($no = curl_errno($ch)) {
        return false;
    }
    curl_close($ch);
    echo $res;
    return json_decode($res, true);
}

移動またはコピーは、同じユーザー内のフォルダーに限ります。共有されているフォルダーやファイルにLive Connectではアクセスできません。また、ひとつのアクセストークンでは、ひとりのユーザーリソースにしかアクセスできないため、必然的に同じユーザー内のフォルダーとなります。

ほかのユーザーへのフォルダーやファイルの移動・コピーは、SkyDrive自体も機能を提供していませんが、Live Connectを利用したWebアプリであればそういった機能も実現できそうですね。複数のユーザーから認可を受け、Webサーバーを中継してファイルを送るような仕組みを作れば可能です。

おわりに

今回はここまでです。基本的なフォルダーやファイル操作に関する内容を紹介しました。あわせてPHPの簡単なサンプルコードも紹介しました。処理している内容は単純なHTTPアクセスだけですので、ほかの言語でも容易に実現できると思います。

今回の内容のファイルのアップロードやフォルダーの作成などは、SkyDriveのWebサイトでもちろんできる内容です。ただ、これらを使って少し工夫すると、ユーザー間のファイルコピーのようなWebサイトでは提供されていないことも可能です。このあたりが、APIの使いどころのひとつかもしれませんね。ぜひAPIを利用してアプリを開発してみてください。

次回もSkyDrive APIの続きを紹介します。最終的にはSkyDriveと連携した簡単なアプリも開発する予定です。

おすすめ記事

記事・ニュース一覧