it-swarm.com.de

Bilddatei mit Java HTTP senden POST Verbindungen

Ich versuche, ein Bild mit Java-HTTP-Anforderungen POST an eine Website zu senden.

Ich verwende den hier verwendeten Basiscode Dateien vom Java-Client auf einen HTTP-Server hochladen :

Das ist meine Modifikation:

String urlToConnect = "http://localhost:9000/upload";
File fileToUpload = new File("C:\\Users\\joao\\Pictures\\bla.jpg");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.

URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true); // This sets request method to POST.
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
    writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream()));
    writer.println("--" + boundary);
    writer.println("Content-Disposition: form-data; name=\"picture\"; filename=\"bla.jpg\"");
    writer.println("Content-Type: image/jpeg");
    writer.println();
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileToUpload)));
        for (String line; (line = reader.readLine()) != null;) {
            writer.println(line);
        }
    } finally {
        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
    }
    writer.println("--" + boundary + "--");
} finally {
    if (writer != null) writer.close();
}

// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode); // Should be 200

Ich bekomme am Ende einen 200-Antwort-Code, aber das Bild ist fehlerhaft, wie in zufälligen Farben. Ich denke, es ist ein Fehler bei der Zeichencodierung. Ich habe versucht, UTF-8 wie im ursprünglichen Beispiel zu verwenden, aber das erstellt nur ein beschädigtes Bild.

Ich bin auch zu 100% sicher, dass es kein serverseitiges Problem ist, da ich Rest-Clients wie Advanced Rest Client/Postman verwenden kann und sie ein Bild ohne Probleme senden können.

Kannst du mir helfen, den Fehler herauszufinden? Vielen Dank.

15
asdt11
import Java.io.File;
import org.Apache.http.HttpEntity;
import org.Apache.http.HttpResponse;
import org.Apache.http.HttpVersion;
import org.Apache.http.client.HttpClient;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.entity.mime.MultipartEntity;
import org.Apache.http.entity.mime.content.ContentBody;
import org.Apache.http.entity.mime.content.FileBody;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.Apache.http.params.CoreProtocolPNames;
import org.Apache.http.util.EntityUtils;


public class PostFile {
  public static void main(String[] args) throws Exception {
    HttpClient httpclient = new DefaultHttpClient();
    httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    HttpPost httppost = new HttpPost("http://localhost:9000/upload");
    File file = new File("C:\\Users\\joao\\Pictures\\bla.jpg"");

    MultipartEntity mpEntity = new MultipartEntity();
    ContentBody cbFile = new FileBody(file, "image/jpeg");
    mpEntity.addPart("userfile", cbFile);


    httppost.setEntity(mpEntity);
    System.out.println("executing request " + httppost.getRequestLine());
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity resEntity = response.getEntity();

    System.out.println(response.getStatusLine());
    if (resEntity != null) {
      System.out.println(EntityUtils.toString(resEntity));
    }
    if (resEntity != null) {
      resEntity.consumeContent();
    }

    httpclient.getConnectionManager().shutdown();
  }
}

Verwenden Sie HttpClient , um diesen Code zu ermitteln. Es ist immer besser, stabile Bibliotheken als die von Grund auf von Grund auf zu verwenden, es sei denn, es gibt etwas, das auf individuelle Weise behandelt werden muss.

18
Kris

Reader/Writer-Klassen sind für die Verarbeitung von Textdaten ausgelegt, während Bilder binär sind. Sie müssen Ihre Dateien als binär interpretieren:

FileChannel         in  = new FileInputStream(fileToUpload).getChannel();
WritableByteChannel out = Channels.newChannel(connection.getOutputStream());

in.transferTo(0, fileToUpload.size(), out)

Natürlich müssen Sie noch alle geöffneten Ressourcen schließen. 

3
ursa

Versuch das:

private DefaultHttpClient mHttpClient;
Context context;
public String error = "";

//Contrutor para que metodos possam ser usados fora de uma activity
public HTTPconector(Context context) {
    this.context = context;
}


public HTTPconector() {
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
    mHttpClient = new DefaultHttpClient(params);
}


public void FileClientPost(String txtUrl, File file){
    try
    {
        error = "";
        HttpPost httppost = new HttpPost(txtUrl);
        MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntity.addPart("Image", new FileBody(file));
        httppost.setEntity(multipartEntity);
        mHttpClient.execute(httppost, new PhotoUploadResponseHandler());
    }
    catch (Exception e)
    {
        Log.e(HTTPconector.class.getName(), e.getLocalizedMessage(), e);
        e.getStackTrace();
        error = e.getMessage();
    }
}

//Verifica se a rede esta disponível
public boolean isNetworkAvailable() {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = cm.getActiveNetworkInfo();
    // if no network is available networkInfo will be null
    // otherwise check if we are connected
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    return false;
}

public String Get(String txtUrl){
    try {
        URL url = new URL(txtUrl);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setReadTimeout(10000);
        con.setConnectTimeout(15000);
        con.setRequestMethod("GET");
        con.setDoInput(true);
        con.connect();

        return readStream(con.getInputStream());

    }  catch (ProtocolException e) {
        e.printStackTrace();
        return "ERRO: "+e.getMessage();
    } catch (IOException e) {
        e.printStackTrace();
        return "ERRO: "+e.getMessage();
    }
}


public String Post(String txtUrl){
    File image;

    try {
        URL url = new URL(txtUrl);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setDoInput(true);
        con.setDoOutput(true);
        con.connect();

        //con.getOutputStream().write( ("name=" + "aa").getBytes());

        return readStream(con.getInputStream());
    } catch (ProtocolException e) {
        e.printStackTrace();
        return "ERRO: "+e.getMessage();
    } catch (IOException e) {
        e.printStackTrace();
        return "ERRO: "+e.getMessage();
    }
}


//Usado para fazer conexão com a internet
public String conectar(String u){
    String resultServer = "";
    try {
        URL url = new URL(u);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        resultServer = readStream(con.getInputStream());
    } catch (Exception e) {
        e.printStackTrace();
        resultServer = "ERRO: "+ e.getMessage();
    }

    Log.i("HTTPMANAGER: ", resultServer);
    return resultServer;
}

//Lê o resultado da conexão
private String readStream(InputStream in) {
    String serverResult = "";
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new InputStreamReader(in));
        String line = "";
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        serverResult = reader.toString();
    }   catch (IOException e) {
        e.printStackTrace();
        serverResult = "ERRO: "+ e.getMessage();
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
                serverResult = "ERRO: "+ e.getMessage();
            }
        }
    }
    return  serverResult;
}

private class PhotoUploadResponseHandler implements ResponseHandler<Object>
{
    @Override
    public Object handleResponse(HttpResponse response)throws ClientProtocolException, IOException {

        HttpEntity r_entity = response.getEntity();
        String responseString = EntityUtils.toString(r_entity);
        Log.d("UPLOAD", responseString);
        return null;
    }
}

Heute stoße ich auf die gleiche Ausgabe, ich schrieb einen kleinen nodejs Server, der nur zwei Routen unterstützt, Bilder hochladen und herunterladen.

Der Client sollte eine Java-Klasse sein, die eine Bildnutzlast über HTTP POST multipart/form-data standard an den Server sendet.

Wenn Sie wissen möchten, warum HTTP POST multipart/form-data ist, lesen Sie bitte die Antwort von Ciro Santilli aus diesem Beitrag: Was bedeutet enctype = 'multipart/form-data'?

Zum Glück fand ich diesen schönen und wirklich guten Beispielcode:

https://www.techcoil.com/blog/how-to-upload-a-file-via-a-http-multipart-request-in-Java-ohne--mit-ansonsten-bibliotheken/

Es zeigt, wie wir die Nutzlast eines mehrteiligen http-Körpers manuell ohne externe Bibliothek aufbauen können. Aus meiner Sicht besteht nur eine kleine Einschränkung darin, dass er nur einen mehrteiligen Körper mit einer Datei behandelt.


Da ich keine HTML-Seite hatte, um die generierte POST - Nutzlast auszuloten, habe ich python verwendet, um sie zu generieren und über wireshark auszuliefern.

Python3-Code:

import requests
posturl = 'http://<server>:<port>/<path>'
files = {'image' : open('<file>', 'rb')}
r = requests.post(posturl, files = files)

Nur zur Kenntnis: Wenn wir den Parameter files aus der Anforderung lib mit einem Dict definieren, wird ein Mulipart/Form-Dateninhalt generiert. http://docs.python-requests.org/de/master/user/advanced/#post-multiple-multipart-encoded-files

Wireshark zeigt alles sehr klar und zum Schluss habe ich schließlich Java verschickt:

HttpURLConnection conn =
        (HttpURLConnection) new URL("http://<server>:<port>/<path>")).openConnection();

// some arbitrary text for multitext boundary
// only 7-bit US-ASCII digits max length 70
String boundary_string = "some radom/arbitrary text";

// we want to write out
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary_string);

// now we write out the multipart to the body
OutputStream conn_out = conn.getOutputStream();
BufferedWriter conn_out_writer = new BufferedWriter(new OutputStreamWriter(conn_out));
// write out multitext body based on w3 standard
// https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
conn_out_writer.write("\r\n--" + boundary_string + "\r\n");
conn_out_writer.write("Content-Disposition: form-data; " +
        "name=\"image\"; " +
        "filename=\""+ <File class instance>.getName() +"\"" +
        "\r\n\r\n");
conn_out_writer.flush();

// payload from the file
FileInputStream file_stream = new FileInputStream(<File class instance>);
// write direct to outputstream instance, because we write now bytes and not strings
int read_bytes;
byte[] buffer = new byte[1024];
while((read_bytes = file_stream.read(buffer)) != -1) {
conn_out.write(buffer, 0, read_bytes);
}
conn_out.flush();
// close multipart body
conn_out_writer.write("\r\n--" + boundary_string + "--\r\n");
conn_out_writer.flush();

// close all the streams
conn_out_writer.close();
conn_out.close();
file_stream.close();
// execute and get response code
conn.getResponseCode();

Um die Antwort von POST zu erhalten, lesen Sie einfach den Eingabestrom, auf den über getInputStream () zugegriffen wird, wobei der Code in den Link eingefügt wurde.

0
whati001