ファイルを返すAPIを作ってみました

API

以前作った確認APIを使って、テキストファイルのレスポンスを返すAPIを作ってみました。
レスポンスは「kakunin.txt」という形でダウンロードします。

準備

APIがサーバ内にファイルを生成しますので、ファイルを生成するフォルダを作ります。
 例 )http://192.169.19.129/api/kakuninFileAPI.php の場合
   www/html/api/ の下に [file] フォルダを作成し、パーミッションを703にしておきます。

   ※環境によってパーミッションは変わります(777から順番に減らして実験しました)

プログラム

ファイル名 kakuninFileAPI.php

<?php
// リクエストのメソッドが GET であることを確認します
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    // クライアントのIPアドレスを取得します
    $client_ip = $_SERVER['REMOTE_ADDR'];

    // クライアントのユーザーエージェントを取得します
    $user_agent = $_SERVER['HTTP_USER_AGENT'];

    // レスポンスのデータを配列に格納します
    $now_date = date('YmdHis');
    $response_data = array(
        'date' => $now_date,
        'client_ip' => $client_ip,
        'user_agent' => $user_agent
    );

    // 配列を JSON 形式にエンコードします
    $json_data = json_encode($response_data);

    // ファイル名を指定
    $file_name = "./file/kakunin_$now_date.txt";

    // ファイルにデータを書き込みます
    file_put_contents($file_name, $json_data);

    // ダウンロードするファイルの名前を指定
    $download_filename = 'kakunin.txt';

    // Content-Type を指定します
    header('Content-Type: application/file');

    // ダウンロードするファイルのサイズを指定します
    header('Content-Length: ' . filesize($file_name));

    // ダウンロードファイルの名前を指定します
    header('Content-Disposition: attachment; filename="' . $download_filename . '"');

    // ファイルの内容を出力します
    readfile($file_name);

    // ファイルを削除します
    unlink($file_name);
} else {
    // GET 以外のメソッドが使用された場合はエラーメッセージを返します
    http_response_code(405);
    echo json_encode(array('message' => 'Method Not Allowed'));
}
?>

説明

 APIにアクセスすると、[file]フォルダにレスポンスファイルを作成し、ダウンロードさせるという仕組みです。
 今回はシングルスレッドで構築していますので、1アクセスごとにファイルを削除する方法をとっており、第三者からファイルを見られる心配はありません。
 しかし、threadを使ってマルチレスポンスを行う場合は、第三者からファイルを読み取られないように、ファイルを暗号化する等の仕組みが必要です。

実行結果

APIをキックする様子

ファイルのダウンロードが始まる様子

ダウンロードフォルダの様子

ファイルの内容

{"date":"20240603024253","client_ip":"192.168.19.1","user_agent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/125.0.0.0 Safari\/537.36 Edg\/125.0.0.0"}

jsonファイルなので、拡張子をjsonにしてもよかったと少し思いました。