【发布时间】:2015-04-28 00:10:48
【问题描述】:
如何使用纯java.net来attach a file to a task using the Asana API?
具体来说,我如何向 Asana API 发出格式良好的 HTTP POST multipart/form-data 编码请求,以便成功地将文件附加到任务?
【问题讨论】:
标签: java multipartform-data asana
如何使用纯java.net来attach a file to a task using the Asana API?
具体来说,我如何向 Asana API 发出格式良好的 HTTP POST multipart/form-data 编码请求,以便成功地将文件附加到任务?
【问题讨论】:
标签: java multipartform-data asana
Asana API 期望附件通过带有多部分/表单数据编码文件的 HTTP POST 请求上传到任务:
https://asana.com/developers/api-reference/attachments#upload
正如this answer 中解释的关于换行符的 HTTP 规范,请确保您使用的是\r\n 换行符,因为 Java 会将大多数 println() 方法转换为依赖于平台的 line.separator 并且 Asana 服务器可能无法容忍格式不正确的换行符。
格式良好的 multipart/form-data POST 请求将如下所示:
Authorization: Basic <BASE64_ENCODED_AUTH>
Content-Type: multipart/form-data; boundary=14d07d7cbcf
User-Agent: Java/1.7.0_76
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 141
--14d07d7cbcf
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain
A file
--14d07d7cbcf--
这是一个 Java 实现,它纯粹使用 java.net 类为 Asana 附件 API 手动构建格式良好的 multipart/form-data 编码的 POST 请求:
import org.apache.commons.codec.binary.Base64;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class AttachFileToTask {
// Use HTTP compliant line feeds in the request.
// Note that Java println() methods may use platform dependent line feeds.
private static String LINE_FEED = "\r\n";
public static void main(String[] args) throws Exception {
// Task attachments endpoint
String url = "https://app.asana.com/api/1.0/tasks/<TASK_ID>/attachments";
File theFile = new File("/path/to/file.txt");
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
// Set basic auth header
String apiKey = "<API_KEY>" + ":";
String basicAuth = "Basic " + new String(new Base64().encode(apiKey.getBytes()));
connection.setRequestProperty("Authorization", basicAuth);
// Indicate a POST request
connection.setDoOutput(true);
// A unique boundary to use for the multipart/form-data
String boundary = Long.toHexString(System.currentTimeMillis());
// Construct the body of the request
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
String fileName = theFile.getName();
writer.append("--" + boundary).append(LINE_FEED);
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"").append(LINE_FEED);
writer.append("Content-Type: text/plain").append(LINE_FEED);
writer.append(LINE_FEED);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(theFile), "UTF-8"));
for (String line; (line = reader.readLine()) != null; ) {
writer.append(line).append(LINE_FEED);
}
} finally {
if (reader != null) try {
reader.close();
} catch (IOException logOrIgnore) {
}
}
writer.append(LINE_FEED);
writer.append("--" + boundary + "--").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
writer.close();
} catch (Exception e) {
System.out.append("Exception writing file" + e);
} finally {
if (writer != null) writer.close();
}
System.out.println(connection.getResponseCode()); // Should be 200
System.out.println(connection.getResponseMessage());
}
}
请注意,在个人使用或实用程序脚本开发之外,不鼓励使用 API 密钥进行基本身份验证。为多个用户部署生产应用程序时,请使用 Asana Connect (OAuth 2.0)
【讨论】:
dd if=/dev/random of=/tmp/example.txt count=1024 bs=1024 && echo "END OF FILE" >> /tmp/example.txt 上传并检查任务附件中的“END OF FILE”。