1

我正在尝试编写 Java 代码以使用其文档 API 将文章 PDF 上传到 Mendeley,但我一直收到 500 错误。我是 Java 新手,所以我可能只是使用了错误的代码或库。最终,目标是通过其文档 API 将文章 PDF 发送到 Mendeley,以便我可以检索有关该文章的元数据。

作为参考,这里是我试图在 Java 中复制的 Mendeley API 文档中提供的 curl 代码:

curl 'https://api.mendeley.com/documents' \
    -X POST \
    -H 'Authorization: Bearer ACCESS_TOKEN' \
    -H 'Content-Type: application/pdf' \
    -H 'Content-Disposition: attachment; filename="example.pdf"' \
    --data-binary @example.pdf   

我能够使用 Python 和 requests 库让它工作。当我使用错误的访问令牌时,我收到 401 错误,因此我知道 API 正在接收我的查询。返回的 500 错误不包含其他错误文本。

// setup connection
String url = "https://api.mendeley.com/documents";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);

// set headers
String ACCESS_TOKEN = getApiValue("api_token");        
con.setRequestProperty("Authorization", "Bearer " + ACCESS_TOKEN);
con.setRequestProperty("Content-Type", "application/pdf");
con.setRequestProperty("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

// send PDF
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
File pdfFile = new File(fileName);
byte[] buf = new byte[8192];
InputStream pdfIS = new FileInputStream(pdfFile);
int c = 0;

while ((c = pdfIS.read(buf, 0, buf.length)) > 0) {
    wr.write(buf, 0, c);
    wr.flush();
}

wr.close();
pdfIS.close();

// get results
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();

4

1 回答 1

1

我是在 Mendeley 工作的使用 Java 的软件工程师,所以希望我能很好地回答这个问题。

顺便说一句,您最初的问题表明您收到了 501 响应代码 - 但是,在查看过去 7 天的 Mendeley 日志并且没有看到任何 501 响应代码之后,并且在尝试了您发布的代码之后,我假设你的意思是你有 500 个响应代码 :)

事实证明这里有两个错误在起作用。第一个是 OpenJDK 中的错误(请参阅https://bugs.openjdk.java.net/browse/JDK-8163921https://bugs.openjdk.java.net/browse/JDK-8177439) - 出于某种原因,如果您使用 HttpUrlConnection 但未设置 Accept 标头,则在您发出请求时会插入“默认”Accept 标头。

不幸的是,提供的默认标头无效!因此,您应该已返回 400 错误(错误请求)。要解决此问题,请添加以下代码行,这会向您的请求添加有效的 Accept 标头,从而防止插入格式错误的默认标头:

con.setRequestProperty("Accept", "*/*");

现在一切都应该像您发出 curl 请求一样工作(或者至少,这使它对我有用)!

请注意,我提到应该返回 400 错误(以及有助于调试问题所在的有用消息)。不幸的是,我们这边有一个错误,这意味着当解析格式错误的默认 Accept 标头时,会抛出一个未正确处理的异常。由于我们没有处理异常,所以我们使用的框架默认返回 500。我已经在内部为此提出了一张票,所以希望将来能解决这个问题。

最后,您发送请求的方式(即使用 HttpUrlConnection 类)虽然可以工作,但却是相当低级的——这使您的事情变得比它必须的要复杂一些。我建议使用一个库,它允许您发送请求而不必担心一些细节,例如Jetty HttpClientApache HttpComponents 库

我希望这会有所帮助!

于 2019-04-01T16:44:38.363 回答