msano / Dockerコンテナがホストするアプリを使い、FTPサーバーからファイルをダウンロードしたい

Created Thu, 02 Jul 2026 20:57:38 +0000 Modified Thu, 02 Jul 2026 21:03:59 +0000
896 Words

概要

FTPを使い、ファイルをアップロード/ダウンロード/削除できるウェブアプリを作りました。 アプリはDockerコンテナにホストします。

本文ではファイルのダウンロードの実装の際に詰まった箇所について書きます。 この経験を通し、Dockerコンテナでホストするアプリを使いFTPサーバーからコンピューターのハードドライブへの直接ダウンロードはできないことを理解しました。

達成したかったこと

Dockerコンテナにホストするアプリを使い、FTPサーバーにあるファイルをコンピュータのハードドライブにダウンロードすることを目標としました。

ディレクトリは以下の通りです。

my-php-app/
│
├── .devcontainer/                  
│   ├── devcontainer.json   # 開発環境の設定      
│   └── docker-compose.yml  # php, nginxと各コンテナを設定         
│
├── nginx/                  
│   ├── default.conf       
│   └── Dockerfile 
│
├── php_code/                  
│   ├── src/                  
│   │  ├── download.php # ファイルのダウンロードを実装     
│   │  └── index.php            
│   └── Dockerfile
│
└── README.md  

ダウンロードを実行するコードです。(download.php)

$remote_file = filter_input(INPUT_GET, 'download_file', FILTER_UNSAFE_RAW);
$download_dir = '../../downloads/';
$download_file = $download_dir . $remote_file;

ftp_get($conn_id, $download_file, $remote_file, FTP_BINARY)

ftp_get

$download_dirでファイルをダウンロードするディレクトリを決定します。

上記コードではFTPサーバーからダウンロードしたファイルはアプリのルート配下の /downloadsに格納しています。

これをDockerコンテナ内ではなくコンピューターのハードドライブにダウンロードしたいと思いましたが、ディレクトリを ../../../downloadsとすると権限エラーが表示されました。

**Warning**: mkdir(): Permission denied in **/var/www/html/php/src/download.php** on line **9**

調べると、コンピューターのハードドライブにファイルを直接プッシュはできないことがわかりました。

There is no way of pushing a file out to a client’s hard drive (think of the security implications), you can only make it available.

ftp_get() does not download, instead moves file to website root folder

この対応として、FTPサーバーからファイルをアプリにダウンロードした後で、アプリからコンピュータのハードドライブにダウンロードする2段構成としました。

$remote_file = filter_input(INPUT_GET, 'download_file', FILTER_UNSAFE_RAW);
$download_dir = '../../downloads/';
$download_file = $download_dir . $remote_file; // Specify the local path to save the downloaded file

if (!file_exists($download_dir) && !is_dir($download_dir)) {
    mkdir($download_dir);
}

if (ftp_get($conn_id, $download_file, $remote_file, FTP_BINARY)) {

    if (file_exists($download_file)) {
        set_include_path('../../downloads/');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($remote_file) . '"');
        readfile($remote_file, true);
    }

} else {
echo "could not download $remote_file\n";
}

readfile

これにより、無事当初の目標を達成することができました!😇

参考

Establishing FTP Connections in PHP

What is the difference between active and passive FTP? [closed]