LoginSignup
2
2

More than 5 years have passed since last update.

Cocos2d-xでサーバーにファイルアップロード

Last updated at Posted at 2017-11-20

はじめに

ゲームにおいてファイルをアップロードする事はそんなに無いけど
端末変更時のセーブデータ移行などをしたい場合
ゲーム内で生成したデータをサーバーにアップロードしたい場合に役立つ

準備すること

事前知識(Part1~Part2)
アップロードサーバー
Cocos2d-xでのファイルアップロード機構
PHPでのファイル受信処理

Upload.cpp
void Upload::upData(){
    //アップロードしたいfileNameとfliePath
    std::string fileName = "sample.png";
    std::string filePath = "ファイルの置いてあるパス" + StringUtils::format("%s", fileName.c_str());

    //HTTPマルチパートフォームデータ送信の為の区切り、改行など
    std::string boundary = "---------------------------14737809831466499882746641449";
    std::string lineEnd = "\r\n";
    std::string hyphens = "--";

    //ファイルパスからバイナリを取得し文字列として代入する
    Data fileData = FileUtils::getInstance()->getDataFromFile(filePath.c_str());
    unsigned char* bytes = fileData.getBytes();
    std::string data;
    for (unsigned int i = 0; i < fileData.getSize(); i++){
        data += bytes[i];
    }


    //ファイルアップロード時、ファイルと一緒に認証データを送信したい時
    std::map<std::string, std::string> postData = std::map<std::string, std::string>();
    postData["data"] = "complete";
    postData["player"] = StringUtils::format("%i", 1);

    //送信データ作成
    std::string body;
    body += setDataStr(postData);
    body += lineEnd + "Content-Disposition: form-data; name=\"mobileFile\"; filename=\"" + fileName + "\"";
    body += lineEnd + "Content-Type: application/octet-stream";
    body += lineEnd + lineEnd + data;
    body += lineEnd + hyphens + boundary + hyphens + lineEnd;


    auto request = new cocos2d::network::HttpRequest();
    request->setUrl("送信URL");
    request->setRequestType(cocos2d::network::HttpRequest::Type::POST);
    request->setResponseCallback([=](cocos2d::network::HttpClient* client, cocos2d::network::HttpResponse* response){
        if (response->isSucceed()) {
            std::vector<char> *buffer = response->getResponseData();

            //printf("Http Test, dump data: ");
            //for (unsigned int i = 0; i < buffer->size(); i++){ printf("%c", (*buffer)[i]); }
            //printf("\n");
            //if (buffer->size() == 4) return;
        }else {

        }
    });

    std::vector<std::string> contentType;
    contentType.push_back("Content-Type: multipart/form-data; boundary=" + boundary);
    request->setHeaders(contentType);
    request->setRequestData(body.data(), body.size());
    request->setTag("UPLOAD FILE");

    cocos2d::network::HttpClient::getInstance()->send(request);
    request->release();
    //log("%s", body.c_str());
}

std::string Upload::setDataStr(std::map<std::string, std::string>& postMap){
    if (postMap.size() == 0) {
        return "";
    }

    std::string boundary = "---------------------------14737809831466499882746641449";
    std::string lineEnd = "\r\n";
    std::string hyphens = "--";

    std::string postString = "";
    postString += lineEnd + hyphens + boundary;
    for (auto iter = postMap.begin(); iter != postMap.end(); ++iter) {
        postString += lineEnd + "Content-Disposition: form-data; name=\"" + iter->first + "\"";
        postString += lineEnd + lineEnd + iter->second;
        if ((++iter)-- != postMap.end()) {
            postString += lineEnd + hyphens + boundary;
        }
    }

    postString += lineEnd + hyphens + boundary;

    return postString;
}

知っていると便利

いまさら聞けないHTTPマルチパートフォームデータ送信
このサイトではHTTPマルチパートフォームデータ送信の仕方が書いてある
これを読むと上記プログラムで何をしているかわかる

sample.php
<?php
//認証する場合
if($_POST["data"] == "complete") {
    $inputData = $_POST;
}else{ exit; }

if ($inputData == NULL) { exit; }

$playerNo = $inputData["player"];

//アップロードファイルを作る時のname
$base = 'mobileFile';
$file = basename($_FILES[$base]['name']);

//アップロードするパスを入力、この時フォルダーが無いと失敗
$uploaddir = 'アップロードフォルダーパス';
existCreateDirectry($uploaddir);

$uploadfile = $uploaddir . $file;

if (move_uploaded_file($_FILES[$base]['tmp_name'], $uploadfile)) {
    //echo "uploaded:".$file;
}else {
    //echo "error";
}

function existCreateDirectry($uploaddir){
    if(!file_exists($uploaddir)){
        if(mkdir($uploaddir, 0777)){
            chmod($uploaddir, 0777);
            //echo "作成に成功しました";
        }else{
            //echo "作成に失敗しました";
        }
    }else{
        //echo "作成しようとしたディレクトリは既に存在します";
    }
}

次回

plistの使い方

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2