文件下载Android中的HttpURLConnection中的授权失败

时间:2013-01-23 03:11:14

标签: android authorization download httpurlconnection urlconnection

我想从Android服务器下载一个zip文件,为此我使用下面的代码。它还需要授权,因此我在URL连接的请求中传递用户名和密码。但我总是得到 401-Response代码(未经授权)

代码: -

protected String doInBackground(final String... params) {
            int count;
            try {
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    /*Authenticator.setDefault(new Authenticator(){
                        protected PasswordAuthentication getPasswordAuthentication() {
                            return new PasswordAuthentication(Constants.USERNAME,Constants.PASSWORD.toCharArray());
                        }});*/

                    Log.i(TAG, "URL == " + params[0]);
                    final URL url = new URL(params[0]);
                    final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    final String auth = new String(Constants.USERNAME + ":" + Constants.PASSWORD);
                    connection.setRequestProperty("Authorization", "Basic " + Base64.encodeToString(auth.getBytes(), Base64.URL_SAFE));
                    //connection.addRequestProperty("Authorization", "Basic " + Base64.encodeToString(auth.getBytes(), Base64.DEFAULT));
                    connection.setUseCaches(false);
                    connection.setConnectTimeout(5000);
                    connection.setDoOutput(true);
                    connection.connect();
                    Log.i(TAG, "Response == " + connection.getResponseMessage());
                    Log.i(TAG, "Response Code == " + connection.getResponseCode());

                    // download the file
                    final InputStream input = new BufferedInputStream(connection.getInputStream());
                    // Path to the just created empty db

                    // this will be useful so that you can show a tipical 0-100% progress bar
                    lenghtOfFile = connection.getContentLength();
                    lengthOfFileInMB = lenghtOfFile / 1048576;
                    Log.i(TAG, "File Size in MB = " + lengthOfFileInMB);

                    outFileName = Environment.getExternalStorageDirectory() + File.separator + ZIP_NAME;
                    final File file = new File(outFileName);
                    if (!file.exists()) {
                        file.createNewFile();
                    }

                    // Output stream
                    final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
                    final byte data[] = new byte[lenghtOfFile];
                    long total = 0;

                    while ((count = input.read(data)) != -1) {
                        total += count;
                        publishProgress("" + total);
                        bufferedOutputStream.write(data, 0, count);
                    }
                    bufferedOutputStream.flush();
                    bufferedOutputStream.close();
                    input.close();
                } else {
                    Toast.makeText(DashboardActivity.this, "MEDIA IS NOT MOUNTED.", Toast.LENGTH_LONG).show();
                }
            } catch (final MalformedURLException e) {
                flag = false;
                Log.e(TAG, e.getMessage(), e);
            } catch (final FileNotFoundException e) {
                flag = false;
                Log.e(TAG, e.getMessage(), e);
            } catch (final IOException e) {
                flag = false;
                Log.e(TAG, e.getMessage(), e);
            } catch (final Exception e) {
                Log.e(TAG, e.getMessage(), e);
            }

            return null;
        }

我在同一服务器中使用Web服务,并且为了获取JSON / XML响应,我使用了DefaultHttpClient。这工作得很好,我也得到了响应代码。我不知道为什么它在URLConnection时没有授权。

这是代码。

String line = null;
        try {
            final URL urlObj = new URL(url);
            final HttpHost host = new HttpHost(urlObj.getHost(), urlObj.getPort(), urlObj.getProtocol());
            final HttpParams httpParameters = new BasicHttpParams();
            // Set the timeout in milliseconds until a connection is established.
            HttpConnectionParams.setConnectionTimeout(httpParameters, Constants.CONNECTION_TIME_OUT);
            // Set the default socket timeout (SO_TIMEOUT) 
            // in milliseconds which is the timeout for waiting for data.
            HttpConnectionParams.setSoTimeout(httpParameters, Constants.CONNECTION_TIME_OUT);

            final DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
            final AuthScope scope = new AuthScope(urlObj.getHost(), urlObj.getPort());
            final UsernamePasswordCredentials creds = new UsernamePasswordCredentials(Constants.USERNAME, Constants.PASSWORD);
            final CredentialsProvider credentialProvider = new BasicCredentialsProvider();
            credentialProvider.setCredentials(scope, creds);
            final HttpContext credContext = new BasicHttpContext();
            credContext.setAttribute(ClientContext.CREDS_PROVIDER, credentialProvider);

            final HttpGet job = new HttpGet(url);
            job.addHeader("USER-AGENT", userAgentString);
            final HttpResponse httpResponse = httpClient.execute(host,job,credContext);

            final HttpEntity httpEntity = httpResponse.getEntity();

            try {
                line = EntityUtils.toString(httpEntity);
            } catch (final ParseException e) {
                line = "Error";
                Log.e("Parse Error", e.getMessage().toString());
            } catch (final IOException e) {
                line = "Error";
                Log.e("IOException Error", e.getMessage().toString());
            }
            final StatusLine status = httpResponse.getStatusLine();
            Log.d("Authentication Status = ", status.toString());
        } catch (final ClientProtocolException e1) {
            line = "Error";
            Log.e("ClientPrtocol Error", e1.getMessage().toString());
        } catch (final ConnectTimeoutException e1) {
            line = "ConnectionTimeOut";
            Log.e("Connection Error", e1.getMessage().toString());
        } catch (final IOException e1) {
            Log.e("IO Error", e1.getMessage().toString());
            line = "Error";
        }

我还尝试在URLConnection中添加以下代码进行身份验证,但这对我也没有用。

Authenticator.setDefault(new Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
     return new PasswordAuthentication(loginNameString, passwordString.toCharArray());
  }
});

问题: -

1)服务器端或android端是否有问题?

2)我可以使用我拥有的defaulthttpclient代码下载文件吗?如果是,任何线索如何下载它,因为我认为我只能从这种方式获取内容而不是整个文件。

2 个答案:

答案 0 :(得分:1)

似乎使用HttpClient是一种更直接的方式,也可以在Android上使用。

我将跳过身份验证部分,因为您的代码对我来说很合适,并且根据您的评论,下面的代码部分应该可以正常工作。这是我自己的项目中典型的读取和复制&写入IO操作代码。

   HttpGet httpget = new HttpGet(url);
    //
    // Authorization configuration code here ...
    // 
    HttpResponse response = httpClient.execute(httpget);
    HttpEntity entity = response.getEntity();

    //
    // The content is all cached in memory for demonstration only, 
    // you can also write to file system using FileOutputStream.
    //
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    if (entity != null) {
        InputStream inputStream = entity.getContent();

        byte[] buf = new byte[1024];
        int read = 0;

        try {
            while ((read = is.read(buf)) >= 0) {
                baos.write(buf, 0, read);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {is.close();} catch (Exception ex) {}
            try {baos.close();} catch (Exception ex) {}
        }
    }

    byte[] content = baos.toByteArray();

答案 1 :(得分:0)

我认为你需要添加connection.setDoInput(true)否则我很确定你无法获得输入流(你可以在同一个连接上同时拥有doInputdoOutput)这可能无法回答您的确切问题,但肯定会阻止您下载。

编辑:没有setDoInput(true)可能会阻止下载,我在你的代码中看不到