如何使用apache httpClient API将file + api密钥和其他参数作为单个请求发送?

时间:2016-03-30 09:11:08

标签: java apache api apache-httpclient-4.x

我已经开始测试http客户端apache API了。我需要它,因为我想发送请求并接收对virustotal API的响应。病毒总API需要发布请求中的参数:

  1. api键值(每个用户的唯一值)
  2. 我从他们的网站上了解到的文件本身。
  3. 例如:

    >>> url = "https://www.virustotal.com/vtapi/v2/url/scan"
    >>> parameters = {"url": "http://www.virustotal.com",
    ...               "apikey": "-- YOUR API KEY --"}
    >>> data = urllib.urlencode(parameters)
    >>> req = urllib2.Request(url, data)
    

    目前,我正在尝试用Java而不是Python做同样的事情。以下是我的源代码的一部分,用于指导整个步骤:

      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      //create post request
      HttpPost request = new HttpPost("https://www.virustotal.com/vtapi/v2/file/scan");
      //http json header
      request.addHeader("content-type", "application/json");
    
      String str  = gson.toJson(param);
    
      String fileName = UUID.randomUUID().toString() + ".txt";
    
      try {
        //API key
        StringEntity entity = new StringEntity(str);
        Writer writer = new BufferedWriter(new FileWriter(fileName));
        writer.write(VirusDefinitionTest.malware());
        request.setEntity(entity);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      MultipartEntityBuilder builder = MultipartEntityBuilder.create();
      FileBody fileBody = new FileBody(new File(fileName)); 
    
      builder.addTextBody("my_file", fileName);
      HttpEntity entity = builder.build();
      request.setEntity(entity);
    
      HttpResponse response;
      try {
        response = httpClient.execute(request);
    

    ...

    不幸的是,我收到了HTTP / 1.1 403 Forbidden。显然,错误是在实体的某个地方,但我找不到如何做到这一点。任何帮助都会受到热烈欢迎。

2 个答案:

答案 0 :(得分:2)

这适用于Apache 4.5.2 HttpClient:

CloseableHttpClient httpclient = HttpClients.createDefault();
try {
    HttpPost httppost = new HttpPost("https://www.virustotal.com/vtapi/v2/file/scan");

    FileBody bin = new FileBody(new File("... the file here ..."));
    // the API key here
    StringBody comment = new StringBody("5ec8de.....", ContentType.TEXT_PLAIN);

    HttpEntity reqEntity = MultipartEntityBuilder.create()
            .addPart("apikey", comment)
            .addPart("file", bin)
            .build();

    httppost.setEntity(reqEntity);

    System.out.println("executing request " + httppost.getRequestLine());
    CloseableHttpResponse response = httpclient.execute(httppost);
    try {
        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        HttpEntity resEntity = response.getEntity();
        if (resEntity != null) {
            System.out.println("ToString:" + EntityUtils.toString(resEntity));
        }
        EntityUtils.consume(resEntity);
    } finally {
        response.close();
    }
} finally {
    httpclient.close();
}

重要的部分是reqEntity,必须有两个专门命名的字段"apikey""file"。使用有效的API密钥运行此代码可以获得API的预期响应。

答案 1 :(得分:1)

问题似乎是首先添加明确的"内容类型"标题是" application / json"最后你发送了Muiltipart实体。您需要将所有参数和文件添加到Muiltipart实体。现在参数不会发送,因为它们被Muiltipart实体覆盖:

CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//create post request
HttpPost request = new HttpPost("https://www.virustotal.com/vtapi/v2/file/scan");
//http json header
request.addHeader("content-type", "application/json");

String str  = gson.toJson(param);

String fileName = UUID.randomUUID().toString() + ".txt";

try {
//API key
StringEntity entity = new StringEntity(str);
Writer writer = new BufferedWriter(new FileWriter(fileName));
writer.write(VirusDefinitionTest.malware());
// --> You set parameters here !!!
request.setEntity(entity);
} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
FileBody fileBody = new FileBody(new File(fileName)); 

builder.addTextBody("my_file", fileName);
HttpEntity entity = builder.build();
// --> You overwrite the parameters here !!!
request.setEntity(entity);

HttpResponse response;
try {
 response = httpClient.execute(request);