我想从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代码下载文件吗?如果是,任何线索如何下载它,因为我认为我只能从这种方式获取内容而不是整个文件。
答案 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)
否则我很确定你无法获得输入流(你可以在同一个连接上同时拥有doInput
和doOutput
)这可能无法回答您的确切问题,但肯定会阻止您下载。
编辑:没有setDoInput(true)可能会阻止下载,我在你的代码中看不到