まえがき
・前回は、登録、ログイン、投稿の3ステップを記載
・前回の延長線上で画像付きの投稿もやってみよと思い立つ
・画像やmime/typeは固定で記述してるので適宜変更してください。
・今回もmastdn.jpを使用しています。適宜変更してください。
・タイトルのことが出来る処理の流れを主軸に記述しているため、ForceUnwrap等よくない書き方は意図的にしています。(早めに直します・・・)
準備
Data型の拡張
extension Data {
public mutating func append(_ string: String) {
let data = Data(string.utf8)
return self.append(data)
}
}
追加メソッド
// 今回はPNG固定でファイル名とmime/typeを使用
let filename = "hoge.png"
let mimetype = "image/png"
// Create body for media
func createBodyWith(parameters: [String: String]?, filePathKey: String?, imageData: Data, boundary: String) -> Data {
var body = Data();
if let parameters = parameters {
for (key, value) in parameters {
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.append("Content-Type: \(mimetype)\r\n\r\n")
body.append(imageData)
body.append("\r\n")
body.append("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
Step.1 前回の内容を使ってログイン
上記の前記事を参考に、access_tokenを取得します。
Step.2 画像をアップロード
// 画像アップロード先URL
let uploadUrl = URL(string: "https://mastdn.jp/api/v1/media")!
// params生成
// access_token: Step.1で取得しているもの
let params: [String: String] = ["access_token": responseJson["access_token"] as! String]
// imageData生成
let imageData = UIImagePNGRepresentation(UIImage(named: filename)!)!
// boudary生成
let boundary = generateBoundaryString()
// request生成(前回作ったメソッドが使えないため、地道にValue追加)
var request = URLRequest(url: urlString!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpBody = createBodyWith(parameters: params, filePathKey: "file", imageData: datas, boundary: boundary)
// 画像アップロードPOST
let task = session.dataTask(with: request, completionHandler: { data, response, error in
do {
self.responseJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>
} catch {
}
})
task.resume()
// responseJsonの中身
{
"id": 12356,
"preview_url": "https://mastdn.jp/system/media_attachments/files/000/069/064/small/b804bb6a6c8db3d2.png?1492450358",
"text_url": "https://mastdn.jp/media/hOgVBgaqylfQM-IolQw",
"type": "image",
"url": "https://mastdn.jp/system/media_attachments/files/000/069/064/original/b804bb6a6c8db3d2.png?1492450358"
}
Step.3 画像ID付きでTootの投稿
// 前回のToot投稿に画像アップロード時のidを付加するだけ
// TootURL
let tootUrl = URL(string: "https://mastdn.jp/api/v1/statuses")!
// access_token: Step.1で取得しているもの
// status: Tootの内容
// media_ids: Step.2で取得したid(最大4つまで)。値は配列に格納。
// visibility: 公開範囲。(省略可能)
let body: [String: String] = ["access_token": responseJson["access_token"] as! String, "status": "開発アプリからのテスト投稿", "visibility": "public", "media_ids": [responseJson["id"]] as AnyObject]
// Toot POST
do {
try post(url: tootUrl, body: body) { data, response, error in
// dataは返ってくるが、投稿できるまでの処理を書くだけなので省略
}
} catch {
}