关于httpurlconnection getcontentlength返回值为-1的问题

在使用AsyncTask进行异步网络请求时,遇到httpUrlConnection通过getContentLength()获取数据长度返回-1的问题,这使得进度条无法正常显示。文章详细探讨了这个问题的原因,并提供了相应的解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在做AsyncTask异步任务读取网络数据的时候,发现了httpUrlConnection的获取数据内容长度(connection.getContentLength())总是为-1。导致进度条一直为灰色状态。预期结果应如图所示:


而现在的效果是这样的:


MainActivity代码如下:

import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;


public class MainActivity extends ActionBarActivity {

    private Button executeBtn;
    private Button cancelBtn;
    private MyTask myTask;
    private TextView resultTxt;
    public ProgressBar progressBar;

    private View.OnClickListener executeBtnListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           myTask = new MyTask();
            myTask.execute("https://www.baidu.com");
            executeBtn.setEnabled(false);
            cancelBtn.setEnabled(true);
        }
    };
    private View.OnClickListener cancelBtnListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            myTask.cancel(true);

        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        executeBtn = (Button) findViewById(R.id.executeBtn);
        cancelBtn = (Button) findViewById(R.id.cancelBtn);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        resultTxt = (TextView) findViewById(R.id.resultTxt);

        executeBtn.setOnClickListener(executeBtnListener);
        cancelBtn.setOnClickListener(cancelBtnListener);
    }

    public class MyTask extends AsyncTask<String,Integer,String> {

        private static final String TAG = "ASYNC_TASK";

        /**
         * Override this method to perform a computation on a background thread. The
         * specified parameters are the parameters passed to {@link #execute}
         * by the caller of this task.
         * <p/>
         * This method can call {@link #publishProgress} to publish updates
         * on the UI thread.
         *
         * @param params The parameters of the task.
         * @return A result, defined by the subclass of this task.
         * @see #onPreExecute()
         * @see #onPostExecute
         * @see #publishProgress
         */
        @Override
        protected String doInBackground(String... params) {
            try {
                URL url = new URL(params[0]);
                URLConnection connection = url.openConnection();
//                connection.setRequestProperty("Accept-Encoding", "identity");
                long total = connection.getContentLength();
                InputStream inputStream = connection.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buf = new byte[256];
                int count = 0;
                int length = -1;
                while((length = inputStream.read(buf)) != -1){
                    baos.write(buf,0,length);
                    count += length;
                    publishProgress((int)((count/(float)total)*100));
                    Thread.sleep(500);
                }

                inputStream.close();

                return new String(baos.toByteArray(),"utf-8");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }


        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            resultTxt.setText(s);

            executeBtn.setEnabled(true);
            cancelBtn.setEnabled(false);

        }


        @Override
        protected void onProgressUpdate(Integer... values) {
            Log.i(TAG, "onProgressUpdate(Progress... progresses) called");
            progressBar.setProgress(values[0]);
//            System.out.print(values[0]);
        }


        @Override
        protected void onCancelled(String s) {
            super.onCancelled(s);
        }


        @Override
        protected void onCancelled() {
            super.onCancelled();
            resultTxt.setText("cancelled!");
            progressBar.setProgress(0);

            executeBtn.setEnabled(true);
            cancelBtn.setEnabled(false);
        }
    }

}
使用System.out.println()输出total为-1,肯定是connection.getContentLength()有问题,现在来看一下这个方法的api:By default, this implementation of HttpURLConnection requests that servers use gzip compression. Since getContentLength() returns the number of bytes transmitted, you cannot use that method to predict how many bytes can be read from getInputStream(). Instead, read that stream until it is exhausted: whenread() returns -1.原来获取的数据是采用gzip压缩的格式的,所以读不出来数据。找到了问题就该找解决办法了,在connection.getContentLength()前面加上使用
connection.setRequestProperty("Accept-Encoding", "identity");
setRequestProperty主要是设置HttpURLConnection请求头里面的属性,比如请求内容格式、Cookie、User-Agent(浏览器类型)等等。

最后实现效果如图所示:



最终结果:


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值