NCMBにPythonでファイルをアップする

NCMBのREST-APIをPythonから利用します。

世にファイルを共有する方法は数多とありますが、今回はmBaaSを利用した方法をやってみます。mBaaSとはMobile Backend as a Serviceの略でスマホなどのモバイル機器からインターネットを介して利用するデータベースチックなものです。

NCMBについて

正式名称はニフクラ Mobile Backendだと思います。私が利用しはじめたころはニフティクラウド Mobile Backendとハッキリとニフティを冠していたのですが、いつの間にか略称が正式名称になってました。ドメインを変更してまで(=APIのエンドポイントを変えてまで)niftyが消えました。大人の事情でしょうか。

と、調べてみたら大人の事情でした。ニフティが富士通と縁が切れてたのをこれで初めて知りました。NCMBは富士通とつながっている方の元ニフティな会社が運営しています。

NCMBはmBaaSなので、スマホアプリのバックエンドとしての機能は当然そろっていますが、REST-APIが用意されており、スマホからに限らずHTTPでアクセスできればデータを出し入れできます。すなわちPythonからだろうとVBAからだろうと利用できます。

アカウントは無料で作成できます。無料アカではAPIコール数などに制限がかかりますが、今回のような限られた人数しか利用しないような場合には必要十分な内容となっております。詳細は公式サイトをご確認ください。

mBaaSをモバイル以外で使う

mBaaSとしてはGoogleのFirebaseが有名ですが、これをPythonやらVBAやらで扱おうとしたんですが、多分できるのでしょうが、環境構築の段階でステップが多すぎて私のスキルと忍耐力では無理でした。

NCMBでは事前のSDKのインストールやら何やらは一切不要で、管理サイトでいくつか設定をすれば、あとはリクエストを正しく送信できさえすればOKです。あらかたの機能はREST-APIで呼べるのですが、一番簡単に使えるファイルストアをPythonから操作してみましょう。

ファイルストアはその名の通り、ファイルをバックエンドサーバーへ保存できる機能です。ファイルへのリンクURLを公開して配信することもできます。これでWEBサーバーを持っていなくても簡単なWEBページなら運用できます。

REST-APIでPythonからファイルを定期的に書き換えることで、最新情報の共有に利用できます。たとえば社内に送った返信必須のメールの返信をPythonにスケジュールでチェックさせ、誰が返信して、誰が返信していないかを一覧表にして公開しておけば、いつまでも返信しない人に無言のプレッシャーをかけることができますね。

公開URLはデフォルトでは知っていれば誰でも制限なしにアクセス可能ですが、会員機能を併用すると、細かいアクセス制限も出来ます(今回はやりません)。

REST-APIでファイルアップロード

例に挙げた、メール返信状況をWEBページで共有するしくみを作ってみます。

REST-APIを利用するにあたり、一番面倒なのがリクエストヘッダーに付与する署名(認証情報)の作成処理です。とにかく手順が多くて大変なのですが、この部分はNCMBの中の人が公開しているサンプルのソースコードがありますので、これを利用します。


では、プログラムしていきます。

まずはグローバルで定数を定義します。それぞれのKEYにはNCMBの管理サイトで発行したものを入れます。importは後で使う分も入っています。標準モジュール以外で必要なのはrequestsだけかな?

署名作成処理はリクエスト毎に変わる部分を引数として関数にしておきましょう。

import hmac
import hashlib
import base64
import datetime
import json
import sqlite3
import urllib.parse
import requests

CLIENT_KEY = 'YOUR CLIENT KEY'
APPLICATION_KEY = 'YOUR APP KEY'
FDQN = 'mbaas.api.nifcloud.com'
API_VERSION = '2013-09-01'

def create_req_header(method, path, queries=None):
    timestamp = datetime.datetime.now().isoformat()
    params = {
        'SignatureMethod': 'HmacSHA256',
        'SignatureVersion': '2',
        'X-NCMB-Application-Key': APPLICATION_KEY,
        'X-NCMB-Timestamp': timestamp
    }

    if queries is not None:
        for k, v in queries.items():
            params[k] = urllib.parse.quote(json.dumps(queries[k]).replace('": "', '":"'))

    params = sorted(params.items(), key=lambda x: x[0])
    ary_sigs = [method, FDQN, f'/{API_VERSION}/{path}']
    query = []

    for k, v in params:
        query.append(f'{k}={v}')

    ary_sigs.append('&'.join(query))
    sign_string = '\n'.join(ary_sigs)

    signature = base64.b64encode(
        hmac.new(
            CLIENT_KEY.encode('UTF-8'),
            sign_string.encode('UTF-8'), hashlib.sha256).digest()).decode()

    headers = {
        'X-NCMB-Signature': signature,
        'X-NCMB-Timestamp': timestamp,
        'X-NCMB-Application-Key': APPLICATION_KEY
    }

    return headers

APIのエンドポイントは機能により変わります。ファイルストアは/files/ファイル名です。これは署名処理にも必要なので、引数として先の関数に渡します。

ローカルのファイルをそのままアップロードもできますが、今回はPythonでHMTLを組み立てて、それをファイルストアへ保存します。

HTMLファイルは1から10まで全部Pythonから出力すると大変なので、変更されることがない部分はテンプレートとして作成しておき、必要なところだけあとから動的に生成し埋め込みます。

NCMBへアップロードする処理を関数にしておきましょう。引数にはHTMLファイル(のテキストデータ)を渡します。

def push_html(text):
    file_name = 'status.html'
    path = 'files/' + file_name
    headers = create_req_header('POST', path)
    url = f'https://{FDQN}/{API_VERSION}/{path}'
    mime_type = 'text/html'
    file_data = text.encode()
    files = {'file': (file_name, file_data, mime_type)}
    requests.post(url, files=files, headers=headers)

テンプレートをtemplate.htmlとして作ります。ページの外枠をHTMLファイルで作成し、Pythonからデータを流し込む場所へプレースホルダーを埋め込みます。**~**がプレースホルダーです。体裁はお手軽にBootstrapでやります。実際にはheadにCDNからの読み込みがありますが、省略しています。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    Bootstrap読み込み(省略)
    <title>返信状況一覧</title>
</head>
<body>
<div class="container">
    <h1>返信状況一覧</h1>
    <div class="text-right">
        last update: **update**
    </div>
        <table class="table table-striped table-dark">
        <tr>
            <th>アドレス</th>
            <th>返信日時</th>
            <th>状況</th>
        </tr>
        **elem**
    </table>
</div>
</body>
</html>

返信状況はメールサーバーからメールを受信してデータベースへ記録しておきます。今回はメール周りの処理は本題ではないので省略します。次の画像のような形式で記録されています。データベースはmail.dbという名前で、テーブル名はlogです。こちらもお手軽にSQLiteです。

ncmb1.png

logテーブルからデータを取得してテンプレートへ展開する処理を関数にします。返信状況に応じてBootstrapのクラスを付け替えて文字の色を変えるようにしてみました。

def create_status_html():
    db = sqlite3.connect('mail.db')
    db.row_factory = sqlite3.Row
    cur = db.cursor()
    status = cur.execute('SELECT * FROM log').fetchall()
    template_path = 'template.html'

    with open(template_path, 'r', encoding='utf-8') as template:
        elem = ''

        for s in status:
            receive_datetime = '' if s['receive_datetime'] is None else s['receive_datetime']

            if receive_datetime != '':
                status_text = '返信済み'
                bs_class = 'text-success'
            else:
                status_text = '未返信'
                bs_class = 'text-danger'

            elem += '<tr>'
            elem += f'<td>{s["address"]}</td>'
            elem += f'<td>{receive_datetime}</td>'
            elem += f'<td class="{bs_class}">{status_text}</td>'
            elem += '</tr>\n'

        t = template.read()
        rt = t.replace('**elem**', elem).replace('**update**', str(datetime.datetime.now()))

    cur.close()
    db.close()
    return rt

次のように関数をコールするとNCMBにHTMLファイルがアップロードされます。

push_html(create_status_html())

NCMBの該当ファイルの配信用URLにアクセスすると

ncmb2.png

メール受信の処理と合わせてスケジュールで実行すれば、最新の情報を自動で配信してくれます。

この他にもNCMBにはNoSQLデータベースやスマホへのプッシュ配信機能などがあるので、興味がある方はアカウントを作成していろいろ遊んでみてください。

おわり。

related pages
フォルダ内の不必要なファイルを一掃する
共有フォルダの放置ファイルを消し去るPythonスクリプト。

社内の共有フォルダなど、複数人が使用する環境あるあるとして、関係のないファイルがいつまでも放置される問題がありますよね。人間が削除していくと「これはまだ使いそうだから本人に確認しようかな?」といった雑念が入り込み作業を邪魔します。そこで血も涙もないコンピューターの出番です。

Read More ...
ExcelブックからPythonでメールを送る
PythonでExcelブックのリストからメール送信。

当然といえば当然なのですが、Pythonでメールの送受信をすることができます。それもBattery Includedの理念にあるように、標準モジュールのみの構成で実現できます。ここに神ツールOpenPyXLを組み合わせると、Excelシートにあるメールアドレス一覧へ片っ端からメールを送信するスクリプトができあがります。

Read More ...
VBAでファイルを開くのが遅すぎるのでPythonで無理矢理に高速化する
VBAとPythonを連携させてファイル読み込み高速化。

我々VBAerにとっては周知の事実ですが、Excel-VBAで時間がかかる処理と言えば、「ワークシートへのアクセス」と「ファイルを開く」です。Pythonでデータ取得してVBAでExcelへ取り込むことでファイルを開く処理を高速化します。

Read More ...
この記事の
作成日

2020-05-21

更新日

2020-06-03

ページ内検索
目次
WEB MASTER
さいた
神エクセル撲滅協会理事(自称)
さいたま市民 埼玉こそ地上の楽園