Created
March 12, 2017 07:52
-
-
Save bvlion/93d708317bba9846de4e29674c5fd003 to your computer and use it in GitHub Desktop.
SlackにJavaからBinaryを送信するサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedReader; | |
import java.io.DataOutputStream; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.io.UnsupportedEncodingException; | |
import java.net.HttpURLConnection; | |
import java.net.ProtocolException; | |
import java.net.URL; | |
import java.nio.charset.StandardCharsets; | |
import java.util.Calendar; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.UUID; | |
import org.apache.commons.lang.StringUtils; | |
import org.apache.commons.lang.time.FastDateFormat; | |
/** | |
* SlackにJavaからBinaryを送信する | |
* @author Bvlion | |
*/ | |
public class SlackBinaryPost { | |
/** 改行コード */ | |
private static final String CRLF = "\r\n"; | |
/** バウンダリのヘッダ(ハイフン2つ) */ | |
private static final String BOUNDARY_HEADER = "--"; | |
/** ファイルアップロード先 */ | |
private static final String SLACK_POST_URL = "https://slack.com/api/files.upload"; | |
/** 読み込みタイムアウト値 */ | |
private static final int READ_TIMEOUT = 10 * 1000; | |
/** 接続タイムアウト値 */ | |
private static final int CONNECTION_TIMEOUT = 10 * 1000; | |
/** HttpURLConnection */ | |
private HttpURLConnection con; | |
/** バウンダリの本体(ハイフン2つ以降) */ | |
private String boundaryBody; | |
/** ファイル名 */ | |
private String fileName; | |
/** 送信データ(byte配列) */ | |
private byte[] fileData; | |
/** タイトル等を入れるマップ */ | |
private Map<String, String> textDataMap = new HashMap<>(); | |
/** | |
* コンストラクタ | |
* @param builder インナークラスBuilder | |
* @throws IOException | |
*/ | |
SlackBinaryPost(Builder builder) throws IOException { | |
this.boundaryBody = "*****" + UUID.randomUUID().toString() + "*****"; | |
this.con = (HttpURLConnection) new URL(SLACK_POST_URL).openConnection(); | |
this.textDataMap = builder.textDataMap; | |
this.fileData = builder.fileData; | |
this.fileName = builder.fileName; | |
createConnection(); | |
} | |
/** | |
* HttpURLConnectionを生成する | |
* @throws ProtocolException | |
*/ | |
private void createConnection() throws ProtocolException { | |
this.con.setRequestMethod("POST"); | |
this.con.setDoOutput(true); | |
this.con.setDoInput(true); | |
this.con.setUseCaches(false); | |
this.con.setReadTimeout(READ_TIMEOUT); | |
this.con.setConnectTimeout(CONNECTION_TIMEOUT); | |
this.con.setRequestProperty("Connection", "Keep-Alive"); | |
this.con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + this.boundaryBody); | |
} | |
/** | |
* 送信する | |
* @return レスポンス | |
*/ | |
public String post() { | |
String data = StringUtils.EMPTY; | |
try { | |
write(); | |
data = read(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
this.con.disconnect(); | |
return data; | |
} | |
/** | |
* データの書き込みを行う | |
* @throws IOException | |
*/ | |
private void write() throws IOException { | |
try (DataOutputStream request = new DataOutputStream(this.con.getOutputStream())) { | |
request.writeBytes(BOUNDARY_HEADER + this.boundaryBody + CRLF); | |
request.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + this.fileName + "\"" + CRLF); | |
request.writeBytes(CRLF); | |
request.write(this.fileData); | |
request.writeBytes(CRLF); | |
// テキストデータの設定 | |
for (Map.Entry<String, String> entry : this.textDataMap.entrySet()) { | |
request.writeBytes(BOUNDARY_HEADER + this.boundaryBody + CRLF); | |
request.writeBytes("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + CRLF); | |
request.writeBytes("Content-Type: text/plain" + CRLF); | |
request.writeBytes(CRLF); | |
request.write(entry.getValue().getBytes(StandardCharsets.UTF_8.toString())); | |
request.writeBytes(CRLF); | |
} | |
request.writeBytes(BOUNDARY_HEADER + this.boundaryBody + BOUNDARY_HEADER + CRLF); | |
} | |
} | |
/** | |
* レスポンスを読み込む | |
* @return レスポンスボディ | |
* @throws UnsupportedEncodingException | |
* @throws IOException | |
*/ | |
private String read() throws UnsupportedEncodingException, IOException { | |
StringBuilder str = new StringBuilder(); | |
try (BufferedReader br = new BufferedReader(new InputStreamReader(this.con.getInputStream(), StandardCharsets.UTF_8.toString()))) { | |
String line; | |
while ((line = br.readLine()) != null) { | |
str.append(line); | |
str.append(System.lineSeparator()); | |
} | |
} | |
return str.toString(); | |
} | |
/** Builder */ | |
public static class Builder { | |
/** token等のテキストデータ */ | |
Map<String, String> textDataMap = new HashMap<>(); | |
/** ファイルのバイトデータ */ | |
byte[] fileData; | |
/** ファイル名 */ | |
String fileName; | |
/** | |
* tokenを設定する | |
* @param token トークン | |
* @return Builder | |
*/ | |
public Builder token(String token) { | |
this.textDataMap.put("token", token); | |
return this; | |
} | |
/** | |
* 送信するチャンネル名を設定する | |
* @param channels チャンネル | |
* @return Builder | |
*/ | |
public Builder channels(String channels) { | |
this.textDataMap.put("channels", channels); | |
return this; | |
} | |
/** | |
* イメージのタイトルを設定する | |
* @param title イメージのタイトル | |
* @return Builder | |
*/ | |
public Builder title(String title) { | |
this.textDataMap.put("title", title); | |
return this; | |
} | |
/** | |
* バイトデータを設定する | |
* @param fileData バイトデータ | |
* @return Builder | |
*/ | |
public Builder fileData(byte[] fileData) { | |
this.fileData = fileData; | |
return this; | |
} | |
/** | |
* ファイル名を設定する | |
* @param fileName ファイル名 | |
* @return Builder | |
*/ | |
public Builder fileName(String fileName) { | |
this.fileName = fileName; | |
return this; | |
} | |
/** | |
* SlackBinaryPostのインスタンスを生成する | |
* @return SlackBinaryPostインスタンス | |
* @throws IOException | |
*/ | |
public SlackBinaryPost build() throws IOException { | |
if (this.fileData == null || this.textDataMap.size() != 3) { | |
throw new IllegalArgumentException("必要データが登録されていません。"); | |
} | |
if (StringUtils.isBlank(this.fileName)) { | |
this.fileName = FastDateFormat.getInstance("yyyyMMddHHmmss").format(Calendar.getInstance()); | |
} | |
return new SlackBinaryPost(this); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dependencyにcommons-langが必要です。