2012-03-04 16 views
0

ライブラリなしで、JavaのPHPスクリプトにファイルをPOSTしたいと思います。ライブラリなしのJavaでのHTTP POST

<form action="http://example.com/upload.php" method="post" enctype="multipart/form-data" name="input"> 
<input type="file" name="image" /><input type="submit" value="Upload file" /> 

その後、私はちょうど/それは$_FILES["image"]とPHPで付属していたすべての情報を、それをつかむことができます。

これは、実際にフォームを持っていた場合はHTMLがどのようになるかです。

example.pngのファイルがある場合(重要なファイルは常にPNGになります)、アップロードしたいのですが、どうすればいいですか?

これは、という名前で常にPOSTすることを想定してはいけないので、File、URL文字列、および別の名前文字列を受け取る関数を作成するのが最も簡単な方法です。その名前でそのURLにファイルをPOSTし、成功したと仮定してURLが返す文字列を返します。

+2

なぜライブラリを使用しないのですか? – Taymon

+0

ライブラリなしでやりたかったのですが、私は通常、JavaでやっているほとんどすべてをスキップしてGUIやすべてを生成することができますが、そのことははるかに少なく学ぶことができるので、それがうまくいかなかったとき、私はHttpClientライブラリを追加しようとしましたが、何らかの理由でEclipseが見ることができませんでした。私は質問をするだろうと思っていました。あなた方がおそらくどちらかの方法で私を助けることができたので、私はライブラリなしでそれをするように頼んでいました。 –

+0

私はあまりにも私が使用するライブラリを制限したい。まず、JDKだけで何ができるのかを見たいと思っています。それから私がそこでそれを見つけることができなければ、私はlibsを探したり、それを自分で書いて恩恵に加えます。 :) – RickHigh

答えて

1

は、サードパーティのライブラリをせずに記述まさに行うコードのためthis articleをチェックしてください。がんばろう!!

+1

これはちょうど私が必要とするように見えます。コードを少し動かす必要がありますが、これは完璧なようです。本当にありがとう! :D –

+0

待って...それは私が説明したものではありません。 PHPが$ _FILES []を使用できるようにこれを変更することはできますか? –

+0

わかりました...私はそうは思わないでしょう。私は自分のコード・サーバー側を変更してそれを修正することができますが、それはちょっとした作業に過ぎません。 –

0

私はあなたのライブラリを使用していない指定実現が、私はApache HttpComponents HttpClientをお勧めします。

あなたの持つ問題の1つは、ファイルをあなたの投稿にエンコードすることです。

-1

あなたは本当にJavaを意味しますかJavaScriptですか? あなたはJavaに言及して以来、私はこれに従います...

私は最も簡単な方法は、整形式の文字列にファイルを取得することであると考えています。あなたがライブラリを使用したくない場合は自己実装が難しい)、あなた自身が正しいHTTPリクエストを送信することでPOSTリクエストを行うことができます。

これは難しいことではありませんが、ここでStackOverflowで説明するにはあまりにも多くのことです。少なくとも、これらのHTTPヘッダーを送信するためには、Javaライブラリを使用することをお勧めします。あなたはJavaクライアントがそれをやっているときに、ブラウザがそれをしないとするときPOSTのボディを見てフィドラーのようなプログラムを使用することができ、要求と応答をデバッグする

0

。クライアントでは、システムプロパティjava.net.useSystemProxiesをtrueに設定して、デバッグ中にFiddlerを使用します。

あなたがマルチパートとしてあなたの体をエンコードした場合、PHPは$ _FILESにファイルを配置します。マルチパートエンコーディングを使用しない場合、Javaコードははるかに簡単ですが、PHPコードで手動でPOSTデータを処理し、サーバー側にファイルを保存する必要があります。これは、エンコーディングが送信されなければならないデータの量を増やすため、より効率的になります。私はエンコーディングが苦痛であると信じるので、エンコーディングしないように傾け、データを送信するだけです.POSコードを手作業で処理するのは難しいでしょう。

あなたがPHPでPOSTデータを取得するには$ HTTP_RAW_POST_DATAにアクセスできるように見えます。アップロードする必要があるファイルが非常に大きい場合、これは機能しません。別の方法があるかもしれません。

EDIT:

ここ受け入れ答えは、Javaを使用してマルチパートPOSTを作成する方法を示しています。Using java.net.URLConnection to fire and handle HTTP requests

0

私はちょうど別の記事でこれを書いています。:)

これを他の人のためにBoonに追加しました。ブーンは小さいです。また、HTTPユーティリティクラスには比較的依存関係がありません。カット/ペーストに問題がある場合は、教えてください。私は必要なビットだけで1つのクラスにすることができます。

あなたが望むビットを分解してみましょう。

http://richardhightower.github.io/site/Boon/Welcome.html

String response = HTTP.postForm ("http://localhost:9220/test", 
      Collections.EMPTY_MAP, 
      map("hI", (Object)"hi-mom", "image", new byte[] {1,2,3}) 
    ); 

https://github.com/RichardHightower/boon

今、あなたは1回のメソッドの呼び出しでそれを行うことができます。 :)

:)

あなたのプロジェクトにコードをカットして通過することができます。 Javaからの標準URLクラスを使用するHTTPという1つのユーティリティクラスがあります。

私はそれをあなたのために打ち砕かせてください。 (あなたがところで、ここでそれをつかむことができます:http://richardhightower.github.io/site/Boon/Welcome.html

を私は(Http Post both string and binary parameters in Java)この記事をもとに恩恵にこれを追加しました:

public static String postForm(final String url, final Map<String, ?> headers, 
              final Map<String, Object> formData 
) 

ここで重要なバイナリデータを符号化されています

String response = HTTP.postForm ("http://localhost:9220/test", 
      Collections.EMPTY_MAP, 
      map("hI", (Object)"hi-mom", "image", new byte[] {1,2,3}) 
    ); 

    boolean ok = true; 
    ok |= response.startsWith ("hI=hi-mom&image=%01%02%03\n") || 
      die("encoding did not work"); 

私は仕様を理解するように動作することを示すテストです。

重要なことは、画像\ u0000 =%01%02%03に新しい画像[] {1,2,3}を変換していることです。

BTWマップは、マップを作成する単なるユーティリティメソッドです(下のリスト)。

httpサーバは単なるエコーです。

return Exceptions.tryIt(String.class, new Exceptions.TrialWithReturn<String>() { 
     @Override 
     public String tryIt() throws Exception { 
      URLConnection connection; 
      connection = doPostFormData(url, headers, formData); 
      return extractResponseString(connection); 
     } 
    }); 

魔法がdoPostFormDataで起こる:

private static URLConnection doPostFormData(String url, Map<String, ?> headers, 
            Map<String, Object> formData 
) throws IOException { 
    HttpURLConnection connection;/* Handle output. */ 


    connection = (HttpURLConnection) new URL(url).openConnection(); 
    connection.setConnectTimeout(DEFAULT_TIMEOUT_SECONDS * 1000); 

    connection.setDoOutput(true); 

    connection.addRequestProperty ("Content-Type", "application/x-www-form-urlencoded"); 

    ByteBuf buf = ByteBuf.create (244); 



    final Set<String> keys = formData.keySet(); 

    int index = 0; 
    for (String key : keys) { 

     Object value = formData.get (key); 

     if (index > 0) { 
      buf.addByte ('&'); 
     } 


     buf.addUrlEncoded ( key ); 
     buf.addByte ('='); 

     if (! (value instanceof byte[])) { 
      buf.addUrlEncoded (value.toString()); 
     } else { 
      buf.addUrlEncodedByteArray((byte[]) value); 
     } 
     index++; 
    } 


    manageContentTypeHeaders ("application/x-www-form-urlencoded", 
      StandardCharsets.UTF_8.name(), connection); 

    manageHeaders(headers, connection); 


    int len = buf.len(); 
    IO.write(connection.getOutputStream(), 
      new String(buf.readForRecycle(), 0, len, StandardCharsets.UTF_8), IO.DEFAULT_CHARSET); 
    return connection; 
} 

お知らせコールを使用して、バイト配列を渡すaddUrlEncodedByteArrayします。 Javaは文字列のURLエンコーディングで正常に動作します。私はちょうどそれを書いたので、私は簡単な方法を見つけることができませんでした バイト配列をエンコードする。

public void addUrlEncodedByteArray (byte[] value) { 



    final byte[] encoded = new byte [2]; 

    for (int index = 0; index < value.length; index++) { 
     int i = value[index]; 

     if (i >= 'a' && i <= 'z') { 
      this.addByte (i); 
     } else if (i >= 'A' && i <= 'Z') { 
      this.addByte (i); 
     } else if (i >= '0' && i <= '9') { 
      this.addByte (i); 
     } else if (i == '_' || i == '-' || i == '.' || i == '*') { 
      this.addByte (i); 
     } else if (i == ' ') { 
      this.addByte ('+'); 
     } else { 
      encodeByteIntoTwoAsciiCharBytes(i, encoded); 
      this.addByte ('%'); 
      this.addByte (encoded [0]); 
      this.addByte (encoded [1]); 
     } 

    } 
} 

これは最善ではありません。しかし、単体テストは機能します。 私はあなたが要点を得ると確信しています。それに応じて仕様に準拠して変換します。

特定の範囲にないすべてのデータは、%hexdigit hexdigitでエンコードされます。

/** 
* Turns a single nibble into an ascii HEX digit. 
* 
* @param nibble the nibble to encode. 
* 
* @return the encoded nibble (1/2 byte). 
*/ 
protected static int encodeNibbleToHexAsciiCharByte(final int nibble) { 

    switch (nibble) { 
     case 0x00: 
     case 0x01: 
     case 0x02: 
     case 0x03: 
     case 0x04: 
     case 0x05: 
     case 0x06: 
     case 0x07: 
     case 0x08: 
     case 0x09: 
      return nibble + 0x30; // 0x30('0') - 0x39('9') 
     case 0x0A: 
     case 0x0B: 
     case 0x0C: 
     case 0x0D: 
     case 0x0E: 
     case 0x0F: 
      return nibble + 0x57; // 0x41('a') - 0x46('f') 
     default: 
      die("illegal nibble: " + nibble); 
      return -1; 
    } 
} 


/** 
* Turn a single bytes into two hex character representation. 
* 
* @param decoded the byte to encode. 
* @param encoded the array to which each encoded nibbles are now ascii hex representations. 
*/ 
public static void encodeByteIntoTwoAsciiCharBytes(final int decoded, final byte[] encoded) { 

    Objects.requireNonNull (encoded); 

    boolean ok = true; 


    ok |= encoded.length == 2 || die("encoded array must be 2"); 


    encoded[0] = (byte) encodeNibbleToHexAsciiCharByte((decoded >> 4) & 0x0F); 
    encoded[1] = (byte) encodeNibbleToHexAsciiCharByte(decoded & 0x0F); 
} 

重要なビットです:

次に、あなただけのエンコーディングを仕上げるためにこれらの2つの方法があります。残りの部分は、HTTPリクエスト/ヘッダーgakを扱うだけです。ここで

はmanageContentTypeHeadersここ

manageContentTypeHeaders ("application/x-www-form-urlencoded", 
      StandardCharsets.UTF_8.name(), connection); 

... 

private static void manageContentTypeHeaders(String contentType, String charset, URLConnection connection) { 
    connection.setRequestProperty("Accept-Charset", charset == null ? StandardCharsets.UTF_8.displayName() : charset); 
    if (contentType!=null && !contentType.isEmpty()) { 
     connection.setRequestProperty("Content-Type", contentType); 
    } 
} 

ですその後、我々はUTF_8で送信するためのストリームをエンコードヘッダ

manageHeaders(headers, connection); 

... 

private static void manageHeaders(Map<String, ?> headers, URLConnection connection) { 
    if (headers != null) { 
     for (Map.Entry<String, ?> entry : headers.entrySet()) { 
      connection.setRequestProperty(entry.getKey(), entry.getValue().toString()); 
     } 
    } 
} 

を管理している:

int len = buf.len(); 
    IO.write(connection.getOutputStream(), 
      new String(buf.readForRecycle(), 0, len, StandardCharsets.UTF_8), IO.DEFAULT_CHARSET); 

IOはちょうどこの行い書く: をIO.write ...

public static void write (OutputStream out, String content, Charset charset) { 

    try (OutputStream o = out) { 
     o.write (content.getBytes (charset)); 
    } catch (Exception ex) { 
     Exceptions.handle (ex); 
    } 

} 

ByteBufはByteBufferと似ていますが、使いやすく、非常に高速です。私はベンチマークを持っています。 :)

私は何を欠席しましたか?

あなたのために働くかどうか教えてください。

--Rick

マップ機能は、私はそれらを大量に使用見つけるように、私は簡潔にマップを表現することができるだけのユーティリティメソッドです。それは9または10にしか行きません。それ以外にも、私はエントリーのリストを渡す方法を持っています。

public static <K, V> Map<K, V> map(K k0, V v0) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    return map; 
} 


public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3, K k4, V v4) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    map.put(k4, v4); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3, K k4, V v4, K k5, V v5) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    map.put(k4, v4); 
    map.put(k5, v5); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3, K k4, V v4, K k5, V v5, K k6, V v6) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    map.put(k4, v4); 
    map.put(k5, v5); 
    map.put(k6, v6); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    map.put(k4, v4); 
    map.put(k5, v5); 
    map.put(k6, v6); 
    map.put(k7, v7); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    map.put(k4, v4); 
    map.put(k5, v5); 
    map.put(k6, v6); 
    map.put(k7, v7); 
    map.put(k8, v8); 
    return map; 
} 

public static <K, V> Map<K, V> map(K k0, V v0, K k1, V v1, K k2, V v2, K k3, 
            V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, 
            K k9, V v9) { 
    Map<K, V> map = new LinkedHashMap<>(10); 
    map.put(k0, v0); 
    map.put(k1, v1); 
    map.put(k2, v2); 
    map.put(k3, v3); 
    map.put(k4, v4); 
    map.put(k5, v5); 
    map.put(k6, v6); 
    map.put(k7, v7); 
    map.put(k8, v8); 
    map.put(k9, v9); 
    return map; 
} 
関連する問題