【发布时间】:2024-01-11 02:26:02
【问题描述】:
这有点奇怪,我已经完成了足够多的研究来找到这个问题的原因和解决方案。我的目标是从需要登录的安全 URL 下载 zip 文件。 当我使用 4.3.6 版的 apache httpClient maven 依赖项时,一切正常。但是,我无法使用此版本,因为我的 aws-sdk-java-core maven 依赖项也具有 httpclient 依赖项,并且使用 v4.3.6 会使 aws-sdk-java 抱怨 NoSuchMethod 运行时异常。我理解这个问题。原因是 apache httpclient v4.3.6 依赖在 maven 依赖树中比 aws-sdk-java-core 依赖使用的版本(4.5.1)更接近。无论如何,我会减少这方面的更多细节,因为我很确定我应该让所有东西都使用一个版本的 Maven 依赖项,而不是使用同一个 jar 的多个版本。 回到原来的问题。由于我不能使用 v4.3.6,我告诉我的代码使用 v4.5.1,这就是文件下载代码开始出现问题的时候。当我使用 httpclient v4.5.1 时,响应给了我以下 html 内容,而不是给我请求的 https url 上的 zip 文件。
<html>
<HEAD><META HTTP-EQUIV='PRAGMA' CONTENT='NO-CACHE'><META HTTP-EQUIV='CACHE-
CONTROL' CONTENT='NO-CACHE'>
<TITLE>SAML 2.0 Auto-POST form</TITLE>
</HEAD>
<body onLoad="document.forms[0].submit()">
<NOSCRIPT>Your browser does not support JavaScript. Please click the
'Continue' button below to proceed. <br><br>
</NOSCRIPT>
<form action="https://githubext.deere.com/saml/consume" method="POST">
<input type="hidden" name="SAMLResponse" value="PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERl">
<input type="hidden" name="RelayState" value="2F1HpzrUy5FdX">
<NOSCRIPT><INPUT TYPE="SUBMIT" VALUE="Continue"></NOSCRIPT>
</form>
</body>
</html>
当我使用 v4.3.6 时,响应为我提供了预期响应的 zip 文件。我尝试通过添加更多代码手动提交此 html 内容,但响应保持不变。 下面提供了我用于文件下载的原始代码。
@Component
public class FileDAO {
public static void main(String args[]) throws Exception{
new FileDAO().loadFile("https://some_url.domain.com/zipball/master","myfile.zip");
}
public String loadFile(String url, String fileName) throws ClientProtocolException, IOException {
HttpClient client = login();
HttpResponse response = client.execute(new HttpGet(url));
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
String unzipToFolderName = fileName.replace(".", "_");
FileOutputStream outputStream = new FileOutputStream(new File(fileName));
writeToFile(outputStream, response.getEntity().getContent());
return unzipToFolderName;
} else {
throw new RuntimeException("error downloading file, HTTP Status code: " + statusCode);
}
}
private void writeToFile(FileOutputStream outputStream, InputStream inputStream) {
try {
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (Exception ex) {
throw new RuntimeException("error writing zip file, error message : " + ex.getMessage(), ex);
} finally {
try {
outputStream.close();
inputStream.close();
} catch (Exception ex) {}
}
}
private HttpClient login() throws IOException {
HttpClient client = getHttpClient();
HttpResponse response = client.execute(new HttpGet("https://some_url.domain.com"));
String responseBody = EntityUtils.toString(response.getEntity());
Document doc = Jsoup.parse(responseBody);
org.jsoup.select.Elements inputs = doc.getElementsByTag("input");
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
HttpPost httpPost = new HttpPost("https://some_url.domain.com/saml/consume");
List<NameValuePair> data = new ArrayList<NameValuePair>();
data.add(new BasicNameValuePair("SAMLResponse", doc.select("input[name=SAMLResponse]").val()));
data.add(new BasicNameValuePair("RelayState", doc.select("input[name=RelayState]").val()));
httpPost.setEntity(new UrlEncodedFormEntity(data));
HttpResponse logingResponse = client.execute(httpPost);
int loginStatusCode = logingResponse.getStatusLine().getStatusCode();
if (loginStatusCode != 302) {
throw new RuntimeException("clone repo dao. error during login, HTTP Status code: " + loginStatusCode);
}
}
return client;
}
private HttpClient getHttpClient() {
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("userId", "password");
provider.setCredentials(AuthScope.ANY, credentials);
return HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
}
}
我仍在分析 4.3.6 以外的 apache httpclient 版本出了什么问题。相同的代码适用于 4.3.6,但不适用于 4.3.6 以上的版本。 非常感谢任何帮助。谢谢大家。
【问题讨论】:
标签: java apache apache-httpclient-4.x