HTTPクライアントサンプルプログラム - ファイルのアップロード

返信する
アバター
eForce技術担当
記事: 193
登録日時: 2014年4月24日(木) 14:18

HTTPクライアントサンプルプログラム - ファイルのアップロード

投稿記事 by eForce技術担当 » 2017年9月06日(水) 21:10

HTTPクライアントサンプルプログラム - ファイルアップロード

μNet3のHTTPクライアントを使用してサーバへファイルをアップロードするサンプルプログラムについて説明します。
ファイルアップロードの仕様は、サーバによります。一般的な方法はありません。
今回のサンプルプログラムでは、サーバ側のスクリプトは、下のURLを参考にしました。
http://php.net/manual/ja/features.file- ... method.php

また、このサンプルプログラムプログラムでは1Mバイトのファイルをアップロードするために、
1Mバイト+α(ヘッダ、区切り)をPOSTしています。
1Mバイトのバッファを用意できないケースを想定しています。
少ないメモリで大きなサイズのデータをPOSTする方法のサンプルでもあります。

コード: 全て選択

/* 1Mバイトのファイルをアップロードするサンプル */
/* ファイル名は1M_bytes.bin */
/*   変更する場合はFILE_SIZEの定義を変更してください。*/
/* ファイルの内容は全て0x55 */
/* POST先はhttp://192.168.0.2/test/file_upload.php */
/*   変更する場合はURL_POST_FILEの文字列を変更してください。*/

#define FILE_SIZE (1024*1024)
#define URL_POST_FILE "http://192.168.0.2/test/file_upload.php"

ER shell_usr_cmd_http_post_file(VP ctrl, INT argc, VB *argv[])
{
    T_HTTP_CLIENT hc;
    T_HTTP_POSTDATA data;
    VB *url = URL_POST_FILE;
    ER ercd;
    UINT i;
    UINT len;
    
    net_memset(&hc, 0, sizeof(hc));
    
    /* URLからサーバーのIPアドレス取得 */
    /* HTTPクライアントで使用するデータ(T_HTTP_CLIENT型)のメンバ変数svrへ格納 */
    ercd = http_get_ipaddr(
               url,            /* URL */
               &hc.svr,        /* IPアドレスを格納する場所 */
               ID_SOC_DNSC,    /* DNSクライアントで使用するソケットのソケットID */
               SPL_DNS_SERVER  /* DNSサーバのIPアドレス */
           );
    if (ercd != E_OK) {
        return ercd;
    }
    
    hc.http_sid = ID_SOC_HTTPC;     /* ソケットID */
    hc.mpf_id   = ID_HTTP_MSG_MPF;  /* 固定長メモリプールのID */
    
    /* 
     * http_cmd_post()の中でPOSTするデータを送信しないので、
     * flagのHTTPC_FLG_SND_BODY_LATERビットをセットしておく
     */
    hc.flag = HTTPC_FLG_SND_BODY_LATER;
    
    /*
     * POSTのデータはファイルの内容以外のデータ(ファイル名、ヘッダ)も送る
     * 
     * 以下送信データ
     *
     *    --BOUNDARY\r\n
     *    Content-Dispsition: form-data; name="userfile"; filename="1M_bytes.bin"\r\n
     *    Content-Type: application/octet-stream\r\n
     *    \r\n
     *    ファイルの内容
     *    \r\n
     *    --BOUNDARY--\r\n
     * ここまで送信データ
     * 上記のバイト数をContent-Lengthヘッダへセットして送信するために、
     * data.buflenへ上記のデータのバイト数をセットする。
     */
    
    net_memset(&data, 0, sizeof(data));
    data.buf = NULL;
    
    net_strcpy(http_buf, 
               "--BOUNDARY\r\n"
               "Content-Disposition: form-data; name=\"userfile\"; filename=\"1M_bytes.bin\"\r\n"
               "Content-Type: application/octet-stream\r\n"
               "\r\n"
    );
    
    data.buflen = net_strlen(http_buf);
    data.buflen += FILE_SIZE;
    data.buflen += sizeof("\r\n"
                          "--BOUNDARY--\r\n") - 1;
                         
    data.contenttype = "multipart/form-data; boundary=BOUNDARY";
    
    /* Postリクエストを送信 (http_cmd_postの処理でサーバと接続する)
     * flagのHTTPC_FLG_SND_BODY_LATERビットがセットされているので、
     * コンテンツの送信とレスポンスの受信は行わない
     */
    ercd = http_cmd_post(&hc, url, &data);
    
    /* コンテンツ送信 (ファイルの内容の直前まで) */
    ercd = http_snd(&hc, (UB*)http_buf, net_strlen(http_buf));
    
    /* ファイルの内容を送信 */
    /* データサイズが大きいので、複数回http_snd()を実行する */
    net_memset(http_buf, 0x55, sizeof(http_buf));
    
    for (i = 0; i < FILE_SIZE; i += len) {
        len = FILE_SIZE - i;
        if (len > sizeof(http_buf)) {
            len = sizeof(http_buf);
        }
        
        ercd = http_snd(&hc, (UB *)http_buf, len);
    }
    
    /* ファイルの内容の後のデータを送信する
     *    \r\n
     *    --BOUNDARY--\r\n
     */
    net_strcpy(http_buf, 
               "\r\n"
               "--BOUNDARY--\r\n");
    ercd = http_snd(&hc, (UB *)http_buf, net_strlen(http_buf));
    
    /* レスポンス(ステータスラインとヘッダ)を受信 */
    ercd = http_rcv_status(&hc);
    
    /* サーバから送られコードを表示 */
    shell_printf(ctrl, "\r\n");
    shell_printf(ctrl, "code = %d\r\n", hc.response.code);
    
    /* サーバから送信されるコンテンツを受信 */
    /* 受信関数の中身はサンプルコードのファイルを参照。
     */
    if (hc.response.chunked) {
        ercd = rcv_chunked_contents(ctrl, &hc);
    } else if (hc.response.contentlen) {
        ercd = rcv_contents(ctrl, &hc);
    } else {
        ercd = rcv_continuous_contents(ctrl, &hc);
    }
    
    /* 切断 */
    http_cls(&hc);
    
    return ercd;
}
■サーバ側のファイル
 下のファイルをサーバのhttp://192.168.0.2/test/***でアクセスできる場所へ置いてください。

 ファイル名
  file_upload.php

コード: 全て選択

<?php
// 4.1.0より前のPHPでは$FILESの代わりに$HTTP_POST_FILESを使用する必要
// があります。

$uploaddir = './';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);
echo $uploadfile;

print "</pre>";

?>
次のファイルを置き、PCのブラウザからアクセスすることで、ファイルをアップロードできます。
(上記のPHPスクリプトの動作確認用、PHPスクリプトと同じディレクトリへ置いてください。)

コード: 全て選択

<!-- データのエンコード方式である enctype は、必ず以下のようにしなければなりません -->
<form enctype="multipart/form-data" action="file_upload.php" method="POST">
    <!-- MAX_FILE_SIZE は、必ず "file" input フィールドより前になければなりません -->
    <!-- <input type="hidden" name="MAX_FILE_SIZE" value="3000000" /> -->
    <!-- input 要素の name 属性の値が、$_FILES 配列のキーになります -->
    このファイルをアップロード: <input name="userfile" type="file" />
    <input type="submit" value="ファイルを送信" />
</form>
ファイルをアップロードすると、サーバへファイルが生成されます。
(PHPスクリプトを置いたディレクトリへ生成されます。)
サーバ側ファイル生成.jpg
サーバ側ファイル生成.jpg (10.76 KiB) 閲覧された回数 17922 回
添付ファイル
sample_httpc.zip
サンプルコード
(4.21 KiB) ダウンロード数: 673 回

返信する