2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Microsoft GraphAPIでドキュメントライブラリの画像を取得する方法(SwiftUI)

Last updated at Posted at 2024-01-30

前置き&概要

以下のようなドキュメントライブラリを作成した場合の画像をGraphAPIを使用して
SwiftUIで取得する方法を紹介します。
一回のGETで画像を取得できるわけではなく、さまざまなIDを取得したのちに画像を取得できます。
情報を探すのに苦労したので、まとめようと思いました。

image.png

今回は他のSharePoint Listと関連させたかったため、"itemImageId"という列を追加し、
そのitemImageIdに紐づく画像を取得する方法を紹介します。
画像をGETしたiPhoneの画面は下記のようになります。

画像を取得した際の動画は以下のようになります。
Simulator Screen Recording - iPhone SE (3rd generation) - 2024-01-22 at 18.50.15.gif

目次

  • 環境、GraphAPI情報
    • 環境、Microsoftアカウント情報、使用パッケージ
    • 画像取得の所要時間
    • 必要なGraphAPIの権限
  • 画像の取得
    • 画像の取得方法
    • コードサンプル
    • 注意点
  • まとめ
  • 引用、アイコン

環境、GraphAPI情報

  • 環境、Microsoftアカウント情報、使用パッケージ

    • 環境
      □ MacBook Air
      □ macOS:Sonoma 14.2.1
      □ XCode:Version 15.0.1

    • Microsoftアカウント情報
      □ Microsoft 365 / Office 365 アカウント [職場または学校]


  • 画像取得の所要時間
    約 1.562 秒(3回の平均。画像を取得するAPI1回の取得時間)
    画像の取得は時間を要するので、非同期で画像を格納し@Stateを使用して
    状態変数にデータを格納することを推奨します。
    時間の計測にはCFAbsoluteTimeGetCurrent()を使用しました。*引用参照

  • 必要なGraphAPIの権限

    • "Sites.Read.All":画像の名前を取得するため
    • "Files.Read":ドキュメントライブラリを取得するため
      *いずれも「委任 (職場または学校のアカウント)」

画像の取得方法

GraphAPIで画像を取得するのは1回のGET操作で取得できます。
しかし、リクエストURLに必要な情報を取得するために複数のGET操作が必須です。
最終的に画像のGETに使用するリクエストURLは下記です。

https://graph.microsoft.com/v1.0/sites/{site-id}/drives/{drive-id}/items/{画像ID}/content

上記の{drive-id}と{画像ID}を取得するために3回のGET操作をします。
site-idの取得方法や各種IDはこちらの記事に詳細を記載しています。

image.png

該当のドキュメントライブラリ(ItemImage)は下記です。

image.png

  • コードサンプル

    • 画像をGETする関数の一部
    MsAuthAdapter.swift
    	func getDriveImage(endPoint: String) async -> Result<UIImage, Stirng> {
    	        var request = URLRequest(url: URL(string: "https://graph.microsoft.com" + endPoint)!)
    	        Logger.msAuthentication.log("リクエスト: \(request)")
    	        guard let accessToken = self.accessToken else { return .failure("noTokenError") }
    	        request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
    	
    	        // APIリクエストを送信
    	        var (data, response): (Data, URLResponse)
    	        do {
    	            (data, response) = try await URLSession.shared.data(for: request)
    	            //                レスポンスを全てプリント
    	            if let responseDataString = String(data: data, encoding: .utf8) {
    	                Logger.msAuthentication.log("Response Data: \(responseDataString)")
    	            }
    	        } catch {
    	            // 原因不明エラー
    	            return .failure("unknownError")
    	        }
    	
    	        // リクエストエラー
    	        guard let httpResponse = response as? HTTPURLResponse,
    	            (200...299).contains(httpResponse.statusCode)
    	        else {
    	            Logger.msAuthentication.error("Request Error")
    	            return .failure("unknownError")
    	        }
    	
    	        // デコード処理
    	        do {
    	            // 結果をUIImageにして返す
    	            guard let image = UIImage(data: data) else {
    	                return .failure("jsonDecodeError")  // catchの役割
    	            }
    	            return .success(image)
    	        }
    	    }
    
    • 画像を取得するボタンと画像の表示
    View.swift
        Button("画像の取得") {
            let result = await msAuthAdapter.getDriveImage(
                    endPoint:
                    "/v1.0/sites/\(siteid)/drives/\(ItemImageDriveID)/items/\(ItemImageId)/content"
                    )
                    switch result {
                    // 結果をUIImageとして返している
                        case .success(let image):
                    // 非同期で画像を格納
                            DispatchQueue.main.async {
                                let newImageData = ShareImageDataModel(image: image)
                            self.sharepointData.imageDataModels.append(newImageData)
                            }
                        case .failure(let error):
                            print(error)
                    }
        }
    
        // 画像の表示
       
    	if let imageData = sharepointData.imageDataModels.first?.image {
            Image(uiImage: imageData)
                .resizable()
                .scaledToFit()
                .frame(maxWidth: 100, maxHeight: 100, alignment: .center)
                .padding(3)
        } else {
            Image(systemName: "photo")
                .resizable()
                .scaledToFit()
                .frame(width: 100, height: 100)
                .padding(3)
            Text("no image")
                .foregroundColor(.gray)
        }
        
    
    • モデル
    Models.swift
    	class SharepointDatas: ObservableObject {
    		@Published var imageDataModels: [ShareImageDataModel] = []  // 画像を配列に格納
    	}
    	
    	// Driveから取得した画像の格納
    	struct ShareImageDataModel: Identifiable {
    	    let id = UUID()  // 一意になるようにSwift側で自動生成
    	    let image: UIImage?
    	}
    
    

エラーハンドリングなどは記載していません。

  • 注意点
    • ドキュメントライブラリの名前を”英語”にしておく(Listとは違い、内部名ではなく表示名が使用される)
    • ドキュメントライブラリの”名前”列は一意の値が入るように運用する(既存の列であり、列の設定で一意の値に設定できないので、運用で補うしかない)GraphAPIで取得できる列がこの列のみ。

まとめ

SwiftUI、SharePoint、Microsoft GraphAPIも使用し始めたばかりの初学者ですので、
他に良い方法や効率的な方法をご存知の方がいらっしゃればご教示いただけますと幸いです。

引用、アイコン、関連記事

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?