質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

8111閲覧

バイナリデータが含まれるbyte型のstring変換でエラーが発生する

suvera

総合スコア106

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2017/02/22 00:33

編集2017/02/22 01:09

###前提・実現したいこと
今までUnity(クライアント)からのリクエストは文字列だけを扱っていて
Unityでjsonの文字列をバイト型に変換したものをリクエストで送信していました。

Python(サーバー)は、受け取ったリクエストのバイト型を
文字列(string)に直し、json.loads()で扱いやすい形にしてから扱うと言った流れで進めていました。

今回起きた問題は画像のデータを扱うことで発生した問題です。
Unity側は画像をバイナリデータで送信するために新しく
WWWFormAddBinaryData()を扱うことになりました。

そして、Python側で送られてきたバイト型のデータを
今まで通り文字列に変換しようとしたところでエラーが発生しました。

stringに変換している理由はjson.loads()がbytesには対応していないからです。

画像はこの後AWSのS3にアップロードしたいため
バイナリか、画像データで扱える状態にしたいです。

###発生している問題・エラーメッセージ
エラーは上記コードの
body = body.decode("utf-8")
行で発生しています。

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 139: invalid start byte

###該当のソースコード

Unity(画像データを送信する側)

C#

1WWWForm form = new WWWForm; 2form.AddBinaryData("testimage", data, null, null); 3uging(UnityWebRequest www = UnityWebRequest.Post(url,form)) { 4 www.SetRequestHeader("Content-Type", "application/json"); 5 yirld return www.Send(); 6}

Python(画像データを受け取る側)

Python

1def on_post(self, req, res): 2 print("POST") 3 # postパラメーターを取得 4 body = req.stream.read() 5 6 # bytes型で受け取るので、文字列に変換する。 7 if type(body) == bytes: 8 body = body.decode("utf-8") 9 data = json.loads(body)

###補足情報(言語/FW/ツール等のバージョンなど)
Mac
Unity5.5,

AWS EC2インスタンス
Nginx
gunicorn
Python3.5
falcon

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

JSON の仕様(RFC 7159)上、バイナリデータを直接扱えません。
JSON では文字列として「UTF-8, UTF-16, UTF-32」のいずれかでなくてはならず、UTF-8 以外は実装の制限で処理されない可能性もあります。

ですので、バイナリデータを渡したければ、バイナリを Base64 変換するなどして、UTF-8 で表現しなおさなくてはなりません。

投稿2017/02/22 01:19

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suvera

2017/02/22 05:31

ありがとうございます。 Unityから送信する際にBase64 を利用して送信してみます。
guest

0

一応、UnityからPython(Falcon)に画像を添付してJSONデータを送信するコードです。

c#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using System.IO; 5using System.Linq; 6using UnityEngine; 7 8public class posttest : MonoBehaviour { 9 10 // JSONとして送るデータのクラス 11 [Serializable] 12 class SendData 13 { 14 public int UserId; 15 public string UserName; 16 } 17 18 // Use this for initialization 19 void Start () { 20 // JSONで送るデータ 21 var userData = new SendData(); 22 userData.UserId = 300; 23 userData.UserName = "Piyo"; 24 25 // 送信する画像数が一定でない場合は配列で扱うほうがいいでしょう。 26 // Resourcesフォルダ配下にある画像ファイルパスを取得 27 string[] extensions = { "bmp", "gif", "jpg", "jpeg", "png", "tif" }; 28 string[] imageFiles = Directory.GetFiles(Path.Combine(Application.dataPath, "Resources"), "*.*") 29 .Where(f => f.EndsWith(".bmp") || f.EndsWith(".gif") || f.EndsWith(".jpg") || f.EndsWith(".jpeg") || f.EndsWith(".png") || f.EndsWith(".tif")).ToArray(); 30 31 32 StartCoroutine(uploadData(userData, imageFiles)); 33 } 34 35 // POST送信メソッド 36 IEnumerator uploadData(SendData userData, string[] uploadImages) 37 { 38 39 var userDataJson = JsonUtility.ToJson(userData); 40 var formData = new WWWForm(); 41 formData.AddField("data", userDataJson); 42 for(var i = 0; i < uploadImages.Length; i++) 43 { 44 FileInfo fileInfo = new FileInfo(uploadImages[i]); 45 var binData = File.ReadAllBytes(uploadImages[i]); 46 formData.AddBinaryData("img" + i, binData, fileInfo.Name); 47 //binData = null; 48 } 49 50 var w = new WWW("http://localhost:8080", formData); 51 yield return w; 52 if (!string.IsNullOrEmpty(w.error)) 53 { 54 print(w.error); 55 } 56 else 57 { 58 print("Finished Uploading Screenshot"); 59 } 60 yield break; 61 } 62}

python

1import falcon 2import os 3import struct 4import json 5from falcon_multipart.middleware import MultipartMiddleware 6 7class HogeResource(object): 8 9 def on_get(self, req, res, filename): 10 res.status = falcon.HTTP_200 11 if filename == '': 12 filename = 'test.html' 13 fn, ext = os.path.splitext(filename) 14 ext = ext.lower() 15 if ext == '.html': 16 res.content_type = 'text/html' 17 elif ext == '.css': 18 res.content_type = 'text/css' 19 elif ext == '.js': 20 res.content_type = 'text/javascript' 21 22 with open(filename, 'r') as f: 23 res.body = f.read() 24 25 def on_post(self, req, res, **kwargs): 26 fidx = 0 27 # JSONで送られるデータは引き続きJSONで取得 28 userData = json.loads(req.params['data'][0]) 29 while True: 30 fparam = req.get_param('img%s' % fidx) 31 if fparam is not None: 32 raw = fparam.file.read() 33 # バイナリーデータでファイルタイプ不明の場合は自力で判定し拡張子を設定 34 ''' 35 ext = '' 36 if raw[0] == 0x89 and raw[1] == 0x50 and raw[2] == 0x4E and raw[3] == 0x47 and raw[4] == 0x0D and raw[5] == 0x0A and raw[6] == 0x1A and raw[7] == 0x0A: 37 ext = '.png' 38 elif raw[0] == 0xFF and raw[1] == 0xD8: 39 ext = '.jpg' 40 elif raw[0] == 0x47 and raw[1] == 0x49 and raw[2] == 0x46: 41 ext = '.gif' 42 elif raw[0] == 0x42 and raw[1] == 0x4D: 43 ext = '.bmp' 44 elif (raw[0] == 0x49 and raw[1] == 0x49) or (raw[0] == 0x4D and raw[1] == 0x4D): 45 ext = '.tif' 46 else: 47 ext = '.bin' 48 ''' 49 here = os.path.dirname(os.path.realpath(__file__)) 50 # ファイル名はユーザー名をプレフィックスにして保存 51 filepath = os.path.join(here, userData['UserName'] + '_' + fparam.filename) 52 #画像ファイルとして書き出す 53 with open(filepath, "wb") as f: 54 f.write(raw) 55 fidx += 1 56 else: 57 break 58 res.body = 'post!!' 59 60app = falcon.API(middleware=MultipartMiddleware()) 61app.add_route('/{filename}', HogeResource())

投稿2017/02/23 11:44

turbgraphics200

総合スコア4267

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

バイナリーデータを受け取る方法はありますが、その前にちょっと質問なのですが、今までもWWWを使用してきたのですか?それと、これはネットワーク対戦のようなものですか?

投稿2017/02/22 09:22

turbgraphics200

総合スコア4267

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suvera

2017/02/23 02:44

今まではJsonの文字列をバイトにしたものを送るような形で渡していました。
turbgraphics200

2017/02/23 02:47 編集

ちょっと具体的にお聞きしたいのが、このサーバーに送るデータはどのようなデータなのでしょう。ネットワーク対戦のように頻繁にアクセスするものなのでしょうか。それとも戦績などといったそれほど頻繁にアクセスする必要のないデータなのでしょうか。
suvera

2017/02/23 03:24

そこまで頻繁ではないはずです。 一クライアントなら一日に数回あったら多い方です。 ただ、アクセスするクライアント数は多くなる予定です。
turbgraphics200

2017/02/23 03:35

すいませんがあともう一つ質問。サーバーに送ったデータはUnityから取得するのでしょうか、それともウェブなどのべつのプラットフォームで公開するといった使い方なのでしょうか?
guest

0

ベストアンサー

受け取る側が json を期待するなら送る側も json で送ればいいんじゃないですか?
Base64 を使いましょう。

投稿2017/02/22 00:44

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suvera

2017/02/22 05:31

ありがとうございます。 Unityから送信する際にBase64 を利用して送信してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問