HttpURLConnection Post: Output stream has no effect?

六眼飞鱼酱① 提交于 2019-12-18 13:38:00

问题


I am developing an Android app and have already found out that different Android versions have a different ways on how they handle Http(s)URLConnections (http://stackoverflow.com/q/9556316/151682).

I ran into the issue that Android 4 performs a POST request over HTTPS nicely, adding headers like Content-Type automatically when running the code below.

However, on Android 2.3.5 (device & emulator), any write to the output stream seems to be ignored - I debugged it with the web proxy Charles and while all headers are sent, the data written to the output stream is not sent along...

Anyone knows how to solve this?

Note: As the API I am developing against has only a self-signed certificate, I need to disable certification validation at this time.

TIA, Patrick

Update In the meantime, I also have tried to following, to no avail:

  • Calling close() after the flush() call on the BufferedOutputStream
  • Calling close() on both the OutputStream and the BufferedOutputStream
  • Using a OutputStreamWriter instead
  • Not calling close() before calling getInputStream()

    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setConnectTimeout(CONNECT_TIMEOUT);
    
    connection.setDoOutput(true); // Triggers POST.
    connection.setRequestMethod("POST");
    int contentLength = 0;
    if(body != null) {
        contentLength = body.getBytes().length;
    }
    
    // Workarounds for older Android versions who do not do that automatically (2.3.5 for example)
    connection.setRequestProperty(HTTP.TARGET_HOST, url.getHost());
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    
    // Set SSL Context -- Development only
    if(context != null && connection instanceof HttpsURLConnection){
        HttpsURLConnection conn = (HttpsURLConnection)connection;
        conn.setSSLSocketFactory(context.getSocketFactory());
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    }
    
    try{
        // Add headers
        if(headers != null){
            for (NameValuePair nvp : headers) {
                if(nvp != null){
                    connection.setRequestProperty(nvp.getName(), nvp.getValue());
                }
            }
        }
    
        connection.setFixedLengthStreamingMode(contentLength);
        OutputStream outputStream = null;
        try {
            if(body != null){
                outputStream = connection.getOutputStream();
                BufferedOutputStream stream = new BufferedOutputStream(outputStream);
                stream.write(body.getBytes()); // <<<< No effect ?!
                stream.flush();
    
            }
        } finally {
            if (outputStream != null) 
                try { 
                    outputStream.close(); 
                }
            catch (IOException logOrIgnore) {
                // ...
            }
        }
    
        InputStream inputStream = connection.getInputStream();
    
        // .... Normal case ....
    
    }
    catch(IOException e){
        // ... Exception! Check Error stream and the response code ...
    
    
    }
    finally{
        connection.disconnect();
    }
    

    }


回答1:


To me it seems that the order in which you call DoSetOutput etc. is the reason for the strange behaviour...

Some links/source with working code for HTTP POST on Android:

  • HttpURLConnection fail on Android (see class in the question as reference)
  • HttpURLConnection (reference including sample code)
  • nice sample including exception handling
  • http://digitallibraryworld.com/?p=189
  • How do I write to an OutputStream using DefaultHttpClient?
  • DefaultHttpClient GET and POST commands Java Android (see code in question)



回答2:


Ah, I finally found it. Looking in the wrong place... The problem was the headers:

My code above actually works fine - the cause is that I included a header which is Base64 encoded. On my Android 2.3.5 the specified option (Base64.DEFAULT) seems to insert an extra newline at the end which ends the request prematurely, giving me no time to send the actual body. On Android 4, the Default seems to be changed to something like BASE64.NO_WRAP as explained in the post linked below...

This was actually already answered here.

Thanks for your efforts.



来源:https://stackoverflow.com/questions/10058516/httpurlconnection-post-output-stream-has-no-effect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!