WordPress 内の PHP から Azure Blob Storage にファイルをアップロードしてみた

WordPress のプラグイン自体に有料オプションで Azure Blob Storage にアップロードする機能があったりします。お金がないので、自分でアップロードする機能だけを作りたいと思いました。そこで今回は、WordPress の無料版 Duplicator プラグインで生成されるファイルを、ボタン一発で Azure Blob Storage にアップロードするプログラムを PHP で作成してみました。

## WordPress 内で検証用プラグインを作成

```bash:bash
cd /var/www/html/wp-content/plugins/

touch duplicator2azureblob.php

chown www-data.www-data duplicator2azureblob.php 

vi duplicator2azureblob.php
```

## 無料版 Duplicator プラグインで生成されるファイル列挙

```php:duplicator2azureblob.php
<?php
/*
 * Plugin Name: duplicator2azureblob
 */

add_action('admin_menu', 'duplicator2azureblob_plugin_settings_page');

function duplicator2azureblob_plugin_settings_page() {
    add_options_page(
        'duplicator2azureblob', // Page Title
        'duplicator2azureblob', // Menu Title
        'manage_options',       // Kengen
        'duplicator2azureblob-plugin-settings', // Page Slug
        'duplicator2azureblob_plugin_settings_page_content' // Callback Function
    );
}

function duplicator2azureblob_plugin_settings_page_content() {
    $wp_content_dir = WP_CONTENT_DIR . '/backups-dup-lite';
    $files = scandir($wp_content_dir);
    $output = '<div class="wrap"><h2>duplicator2azureblob</h2><ul>';
    foreach ($files as $file) {
        $ext = pathinfo($file, PATHINFO_EXTENSION);
        if ($ext === 'zip' || $ext === 'bak') {
            $output .= '<li>' . $file . '</li>';
        }
    }
    $output .= '</ul></div>';
    $output .= '<form method="post" action=""><input type="hidden" name="upload" value="true"><input type="submit" value="Upload"></form>';

    if (isset($_POST['upload'])) {
        $output .= '<div class="updated"><p>Upload Completed</p></div>';
    }
    echo $output;
}
```

![wordpress-azure-blob-upload-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/eab70e34-ee86-c847-22ec-490c64e80efe.png)


## 列挙したファイルを Azure Blob Storage にアップロードする部分を作成

```php:duplicator2azureblob.php
function duplicator2azureblob_file($dir, $file) {
    if (isset($_POST['upload'])) {
        $account = 'mnrlabo';
        $container = 'wordpress';
        $accessKey = '<<<Your Access Key Here>>>';

        $filename = $dir . '/' . $file;
        $body = file_get_contents($filename);
        $size = filesize($filename);
        $type = mime_content_type($filename);
        $date = gmdate('D, d M Y H:i:s T');
        $headers = [
            'x-ms-blob-type:BlockBlob',
            'x-ms-version:2020-04-08',
        ];
        $stringToSign = [
            'PUT', // VERB
            '',    // Content-Encoding
            '',    // Content-Language
            $size, // Content-Length
            '',    // Content-MD5
            $type, // Content-Type
            $date, // Date
            '',    // If-Modified-Since
            '',    // If-Match
            '',    // If-None-Match
            '',    // If-Unmodified-Since
            '',    // Range
        ];

        $stringToSign = implode("\n", array_merge($stringToSign, $headers, ["/$account/$container/$file"]));
        $signature = base64_encode(hash_hmac('sha256', $stringToSign, base64_decode($accessKey), true));

        $httpHeaders = array_merge($headers, [
            "Authorization: SharedKey $account:$signature",
            "Date: $date",
            "Content-Type: $type",
            "Content-Length: $size",
        ]);

        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => "https://$account.blob.core.windows.net/$container/$file",
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_HEADER => false,
            CURLOPT_HTTPHEADER => $httpHeaders,
            CURLOPT_POSTFIELDS => $body,
        ]);
        curl_exec($ch);
        curl_close($ch);
    }
    return $file;
}
```

## ファイル列挙とアップロード処理を合体した最終版のコード

```php:duplicator2azureblob.php
<?php
/*
 * Plugin Name: duplicator2azureblob
 */

add_action('admin_menu', 'duplicator2azureblob_plugin_settings_page');

function duplicator2azureblob_plugin_settings_page() {
    add_options_page(
        'duplicator2azureblob', // Page Title
        'duplicator2azureblob', // Menu Title
        'manage_options',       // Kengen
        'duplicator2azureblob-plugin-settings', // Page Slug
        'duplicator2azureblob_plugin_settings_page_content' // Callback Function
    );
}

function duplicator2azureblob_plugin_settings_page_content() {
    $wp_content_dir = WP_CONTENT_DIR . '/backups-dup-lite';
    $files = scandir($wp_content_dir);
    $output = '<div class="wrap"><h2>duplicator2azureblob</h2><ul>';
    foreach ($files as $file) {
        $ext = pathinfo($file, PATHINFO_EXTENSION);
        if ($ext === 'zip' || $ext === 'bak') {
            $output .= '<li>' . duplicator2azureblob_file($wp_content_dir, $file) . '</li>';
        }
    }
    $output .= '</ul></div>';
    $output .= '<form method="post" action=""><input type="hidden" name="upload" value="true"><input type="submit" value="Upload"></form>';

    if (isset($_POST['upload'])) {
        $output .= '<div class="updated"><p>Upload Completed</p></div>';
    }
    echo $output;
}

function duplicator2azureblob_file($dir, $file) {
    if (isset($_POST['upload'])) {
        $account = 'mnrlabo';
        $container = 'wordpress';
        $accessKey = '<<<Your Access Key Here>>>';

        $filename = $dir . '/' . $file;
        $body = file_get_contents($filename);
        $size = filesize($filename);
        $type = mime_content_type($filename);
        $date = gmdate('D, d M Y H:i:s T');
        $headers = [
            'x-ms-blob-type:BlockBlob',
            'x-ms-version:2020-04-08',
        ];
        $stringToSign = [
            'PUT', // VERB
            '',    // Content-Encoding
            '',    // Content-Language
            $size, // Content-Length
            '',    // Content-MD5
            $type, // Content-Type
            $date, // Date
            '',    // If-Modified-Since
            '',    // If-Match
            '',    // If-None-Match
            '',    // If-Unmodified-Since
            '',    // Range
        ];

        $stringToSign = implode("\n", array_merge($stringToSign, $headers, ["/$account/$container/$file"]));
        $signature = base64_encode(hash_hmac('sha256', $stringToSign, base64_decode($accessKey), true));

        $httpHeaders = array_merge($headers, [
            "Authorization: SharedKey $account:$signature",
            "Date: $date",
            "Content-Type: $type",
            "Content-Length: $size",
        ]);

        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => "https://$account.blob.core.windows.net/$container/$file",
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_HEADER => false,
            CURLOPT_HTTPHEADER => $httpHeaders,
            CURLOPT_POSTFIELDS => $body,
        ]);
        curl_exec($ch);
        curl_close($ch);
    }
    return $file;
}
```

## Azure Blob Storage にファイルアップロード完了

![wordpress-azure-blob-upload-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/6167b023-d25b-d19a-8e91-17cbd79e060b.png)

## 参考

https://learn.microsoft.com/ja-jp/rest/api/storageservices/put-blob-from-url?tabs=shared-key