How do download a file with login using HttpURLCon

2020-03-08 06:01发布

问题:

For my Android app I need to download a file from a site requiring login. It is not basic http authentication but rather form emulation.

Being new to Android I really don't know how to get started, but in PHP it is easy with cUrl:

// Set standard options
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, "somecookiejar");
curl_setopt($ch, CURLOPT_COOKIEFILE, "somecookiefile");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// Login
curl_setopt($ch, CURLOPT_URL, "https://example.com" );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, "username=myusername&password=mypassword");
curl_exec($ch);

// Get the file
curl_setopt($ch, CURLOPT_URL, "http://example.com/files/myfile.mp3");
curl_setopt($ch, CURLOPT_POST, 0 );
writefile(curl_exec($ch), "myfile.mp3");
curl_close($ch);

I would appreciate any help in getting this done in Android.

Note: I mention HttpURLConnection in the subject, but other suggestions are of course more than welcome :)

Edit: I think I should clarify a bit. In the first request to the login form the username and password is set. The server returns a set of cookies which is then handed over to the second request where the actual file download takes place. The code is actually a working example from PHP (albeit anonymized) and my specific problem is handling the cookies between the requests. In cUrl all this cookie stuff happens automatically. Thanks!

回答1:

You going to want to use an HttpClient object in combination with HttpPost, HttpGet, and HttpResponse objects. It is probably easier to just look at an example.

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(context.getString(R.string.loginURL));
HttpResponse response = null;
List<NameValuePair> postFields = new ArrayList<NameValuePair>(2);  

// Set the post fields
postFields.add(new BasicNameValuePair("username", settings.getString("username", "null")));
postFields.add(new BasicNameValuePair("password", settings.getString("password", "null")));
post.setEntity(new UrlEncodedFormEntity(postFields, HTTP.UTF_8));

// Execute the POST request
response = client.execute(post);

Assuming the login was successful, you can now execute GET and POST requests as an authenticated user as long as you execute them though the HttpClient that you executed the login through. It is this object that manages the cookies. Hope this helps!

EDIT: Forgot to mention that you can of course use the HttpRespose object to perform error checking.



回答2:

This is what I came up with helped by S201's answer plus a lot of googling. The code is simplified and without try-catch constructions.

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://example.com/login");
HttpResponse response = null;
List<NameValuePair> postFields = new ArrayList<NameValuePair>(2);

// Set the post fields
postFields.add(new BasicNameValuePair("username", "myusername"));
postFields.add(new BasicNameValuePair("password", "mypassword"));
post.setEntity(new UrlEncodedFormEntity(postFields, HTTP.UTF_8));

// Execute the POST request
response = client.execute(post);

// Now GET the file
HttpGet get = new HttpGet("http://example.com/files/myfile.mp3");
response = client.execute(get);

HttpEntity entity = response.getEntity();
InputStream in = entity.getContent();

// Save the file to SD
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
path.mkdirs();
File file = new File(path, "myfile.mp3");
FileOutputStream fos = new FileOutputStream(file);

byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
        fos.write(buffer, 0, len1);
}

fos.close();