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

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

ただいまの
回答率

90.38%

  • Java

    16465questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • API

    1888questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

  • Webサイト

    1326questions

    一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

  • POST

    283questions

    POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

JAVAでPOSTしたいがエラーがでます

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,150

musicexbp

score 7

前提・実現したいこと

javaでdocomoAPI音声認識にPOSTしたいのですがエラーがでる
https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=speech_recognition&p_name=api_amivoice_1#tag01
APIリファレンスです

発生している問題・エラーメッセージ

必須パラメータがない とエラーが帰ってくる
POSTはできている模様です

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package libs;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 *
 * @author KITT
 */
public class test {

    public test() throws IOException{
        String boundary ="JT49KPkVKrz2Y4YrGhLezUP8fWHU6kARBrpKRpuNsjXm";
        String based=null;//base64に変換後、文字列として格納
        FileSystem fs = FileSystems.getDefault();
        Path p = fs.getPath("C:\\voice.raw");
        Charset charset = StandardCharsets.UTF_8;//キャラセットをUTF-8にする
        byte[] vb = Files.readAllBytes(p);//voice.rawを読み込む
        try {
            URL url =new URL("https://api.apigw.smt.docomo.ne.jp/amiVoice/v1/recognize?APIKEY=XXXXXXXXXXXXXXXXX");//APIkeyは省略
            URLConnection con=url.openConnection();
            con.setDoOutput(true);

            OutputStreamWriter writer=new OutputStreamWriter(con.getOutputStream());
            BufferedWriter bw1 = new BufferedWriter(writer);
            /*送信文字列*/
            bw1.write("Content-Type: multipart/form-data; boundary=<"+boundary+">\r\n--<"+boundary+">\r\nContent-Disposition: form-data; name=\"v\"\r\n\r\n");
            bw1.write("on\r\n--<"+boundary+">\r\n");
            bw1.write("Content-Disposition: form-data; name=\"a\";filename=\"voice.raw\"\r\n");
            bw1.write("Content-Type: application/octet-stream");
            bw1.write("\r\n\r\n"); 
            java.util.Base64.Encoder Encoder = java.util.Base64.getEncoder();
            based=Encoder.encodeToString(vb);
            bw1.write(based);
            bw1.write("\r\n");
            bw1.write("--<"+boundary+">--");
            bw1.flush();
            bw1.close();
            //受信
            InputStream stream = con.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            String responseData = null;
             while((responseData = reader.readLine()) != null){
                  System.out.print(responseData);
             }
              stream.close();
        } catch (MalformedURLException ex) {
            Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }}



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


PYTHONでのPOSTには成功していますが、JAVAでPOSTしたいと思い作成中です

試したこと

APIリファレンス通りに文字列を入力した
文字列のfilenameをvoice.rawにした
キャラセットをUTF-8にしたり、outputstreamのキャラセットをUTF-8にしたりしたが、同じ返答結果になる

補足情報(言語/FW/ツール等のバージョンなど)

netbeans jdk1.8 win10

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

"<"">"こいつら含めたらいけないとか・・・?

境界区切子

追記
含めたらいけなかったです。

API弄って処理が通ったっぽいコードを置いておきます。
変更箇所としては3つ、
・multipartの記述は、multipartの仕様に沿った形に修正("<" ">"を削除)
・一番最初のContent-Typeの設定をsetRequestPropertyで行うように
・音声データはバイナリを直接書き込み
(他にしれっと治ってるところがあるかもしれないです。)

            URL url = new URL("https://api.apigw.smt.docomo.ne.jp/amiVoice/v1/recognize?APIKEY=XXXXXXXXXXXXXXXXX");

            HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
            con.setDoOutput(true);

            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

            OutputStream outputStream = con.getOutputStream();
            outputStream.write(("--" + boundary + "\r\n").getBytes(charset));
            outputStream.write(("Content-Disposition: form-data; name=\"v\"\r\n").getBytes(charset));
            outputStream.write(("\r\n").getBytes(charset));
            outputStream.write(("on").getBytes(charset));
            outputStream.write(("\r\n--" + boundary + "\r\n").getBytes(charset));
            outputStream.write(("Content-Disposition: form-data; name=\"a\"; filename=\"audio_sample_amivoice.raw\"\r\n").getBytes(charset));
            outputStream.write(("Content-Type: application/octet-stream\r\n").getBytes(charset));
            outputStream.write(("\r\n").getBytes(charset));
            outputStream.write(Files.readAllBytes(p));
            outputStream.write(("\r\n--" + boundary + "--\r\n").getBytes(charset));
            outputStream.flush();
            outputStream.close();

            //受信
            InputStream stream = con.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            String responseData = null;
            while ((responseData = reader.readLine()) != null) {
                System.out.println(responseData);
            }

            stream.close();

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/06 20:37

    すみません
    やってみましたが、失敗しました
    たぶん、BASE64でなく、バイナリで送るのだろうと思います
    byte配列をPOSTシたい場合どうすればよいでしょうか
    bw1.writeに配列を指定してもエラーがでます。。。

    キャンセル

  • 2017/10/07 11:13

    ありがとうございます
    このあと、JACKSONというらいぶらりを使い
    textを抽出、結果をかえすことができるようになりました
    これからも、日々精進したいです

    キャンセル

+1

bw1.write("on\r\n--<WZtMKGjB8YjFZgeAcEYCKKZREUD4ah2QxsGarLWDB6yp>\r\n");

バウンダリが違うからでは?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/05 22:28

    変数boundaryと同じものにしましたが、結果は同じでした
    バウンダリは調べますと、乱数であればなんでも良いそうです(被らなければ)

    キャンセル

+1

あなたの提示されたページには以下のようなリクエストサンプルが記載されています。

POST https://api.apigw.smt.docomo.ne.jp/amiVoice/v1/recognize?APIKEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Content-Type: multipart/form-data; boundary=<バウンダリ文字列>

--<バウンダリ文字列>
Content-Disposition: form-data; name="v"

on
--<バウンダリ文字列>
Content-Disposition: form-data; name="a"; filename="sample.adc"
Content-Type: application/octet-stream

音声データ(binary)
--<バウンダリ文字列>--

これに対し、あなたのコードで生成されるリクエストはこうです。

POST https://api.apigw.smt.docomo.ne.jp/amiVoice/v1/recognize?APIKEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Content-Type: multipart/form-data; boundary=<バウンダリ文字列>
Content-Disposition: form-data; name="v"

on
--<バウンダリ文字列と違うランダムな文字列>
Content-Disposition: form-data; name="a"; filename="voice.raw"
Content-Type: application/octet-stream
音声データ(binary)
--<バウンダリ文字列>--

  • Content-Disposition: form-data; name="v"の前にバウンダリと改行が1つ足りない
  • vの後のバウンダリが最初に定義したバウンダリと違う
  • 音声データの前に改行が1つ足りない

の三点です。
実際に生成されるリクエストを想像しながら見比べたら分かる問題です。プログラマに陥りがちな「プログラムは思った通りには動かない、書いたとおりに動く」というやつです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/06 17:49

    コードをなおしてみました
    見落としがあるかもしれませんが、結果は変わらず-2です
    コンソール出力は
    {"code":"-2","message":"\u5fc5\u9808\u30d1\u30e9\u30e1\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093","text":"","utteranceid":"","reserved":""}zzz
    です
    文字化け解消ツールを使うと必須パラメータがないと描いてあります

    キャンセル

  • 2017/10/06 17:59

    Content-Type: multipart/form-data; boundary=<バウンダリ文字列> のあとに改行が1つ足りません。

    キャンセル

  • 2017/10/06 18:28

    ちなみに、送信するデータはバイナリで送る?それともbase64どちらなのでしょう?

    キャンセル

  • 2017/10/06 19:00

    たぶん、バイナリなのかなぁ
    ちょっとわかりませんが、
    そう言われれば、リファレンスにバイナリって書いてあります
    すみませんが、バイナリで送るにはどうしたらいいのでしょうか?
    読み込んだbyte配列をそのまま
    送ってやればいいんでしょうか?

    キャンセル

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

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    16465questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • API

    1888questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

  • Webサイト

    1326questions

    一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

  • POST

    283questions

    POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。