iOS(Swift)から3ステップでMastodonに画像付き投稿を行う

More than 1 year has passed since last update.


まえがき

・前回は、登録、ログイン、投稿の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 前回の内容を使ってログイン

iOSから3ステップでMastodonに投稿する

上記の前記事を参考に、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 {
}


参考にしたURL


  1. Tootsuite documentation

  2. Image upload example with Swift and PHP