前提
指輪型デバイスで取得した心拍や睡眠データを可視化するアプリを作成しようとしています.
同デバイスの開発会社が提供しているAPIではなく, ダウンロード可能なcsv or jsonの生データを元に開発しようと考えています.
ただし, その生データをプログラム上から取得できません.
たとえば,
https://hogehoge1234.com/account/export/sleep/csv (仮のURLです)
というURLにChromeやSafari等のブラウザでアクセスすると,
- 同社のユーザアカウントのログイン画面が表示されるので, ID, PWを入力してログイン (初回のみ)
- (PC) hogehoge_sleep.csv (約700KB) がダウンロードされる
(iOS) hogehoge_sleep.csv をどの方法で開くかが表示される
という挙動となります.
そこで, この hogehoge_sleep.csv をiOSアプリなどで自動ダウンロードできるように,
let (data, urlResponse) = try await URLSession.shared.data(from: url)
を実行したのですが, 実際の生データではなく, data
には3592 bytes
という文字列が返ってきてしまいました.
仮にこれが文字列ではなく生データだと仮定しても, 本来の約700KBより遥かに少ないため不適です.
データ取得の前にアカウント認証の処理が入ることが原因と考えているのですが,
このような場合に, どう処理していけば良いかがわかりません.
現状, PCの場合は, pythonでブラウザを用いてURLにアクセスすることで生データが自動ダウンロードできるため,
そこからファイル移動させて解析する, という無理やりな手法で仮実装しています.
ただし, スマホで気軽に閲覧できるようにswiftでのアプリ開発を始めたのですが, 上記のデータ取得の時点で躓いている, という状況です.
実現したいこと
- Swiftを利用して指定のURLから生データをダウンロードできるようにする
発生している問題・エラーメッセージ
start to get data <NSHTTPURLResponse: 0x6000033a1800> { URL: https://hogehoge1234.com/user/sign-in?next=%2Faccount%2Fexport%2Fsleep%2Fcsv } { Status Code: 200, Headers { "Cache-Control" = ( "no-cache, no-store, must-revalidate" ); "Content-Encoding" = ( gzip ); "Content-Type" = ( "text/html" ); Date = ( "Thu, 10 Nov 2022 08:49:02 GMT" ); Etag = ( "略" ); Expires = ( "no-cache" ); "Last-Modified" = ( "Wed, 02 Nov 2022 20:16:59 GMT" ); Pragma = ( 0 ); Server = ( AmazonS3 ); "Strict-Transport-Security" = ( "max-age=31536000; includeSubDomains" ); Vary = ( "Accept-Encoding" ); Via = ( "略" ); "content-security-policy" = ( 略 ); "x-amz-cf-id" = ( "略" ); "x-amz-cf-pop" = ( "SEA73-P2", "SEA73-P3" ); "x-cache" = ( "Miss from cloudfront" ); "x-content-type-options" = ( nosniff ); "x-frame-options" = ( DENY ); } } 3592 bytes end to get data
該当のソースコード
swift
1 func getData(){ 2 print("start to get data") 3 Task { 4 await get() 5 print("end to get data") 6 } 7 } 8 9 private func get() async { 10 guard let url = URL(string: "https://hogehoge1234.com/account/export/sleep/csv") else { 11 print("url error") 12 return 13 } 14 15 do { 16 let (data, urlResponse) = try await URLSession.shared.data(from: url) 17 print(urlResponse) 18 print(data) 19 } catch { 20 print("get error") 21 } 22 }
試したこと
上記のコード以外に,
- sheetでアプリ内ページとして, 当該ページを開く
ということも試したのですが, この場合, 生データ自体はページ上に表示 (下図) されるのですが, そこからどのようにアプリ内にデータを持っていくべきかで躓いています.
share extensionでアプリの選択肢を表示させるなど, ユーザ操作が必要な方法しかないでしょうか...?
- PC+pythonで仮実装した際は
webbrowser.open('https://hogehoge1234.com/account/export/sleep/csv', new=0, autoraise=True)
を実行して, ブラウザで当該ページを開き, (無理やりですが) 自動ダウンロードできていました.
補足情報(FW/ツールのバージョンなど)
- 開発環境
- Macbook Air (M1 2020) (16GBメモリ, 2TB SSD)
- MacOS 12.6
- XCode 14.1
- 実機
- iPhone 8, 12等
- iOS 16.1