0

我正在使用 AWS Amplify 开发 iOS 应用程序。我通过 S3 添加了存储来托管一些资产,并尝试配置应用程序以下载它们。唯一的问题是我看到的每个示例都有存储桶名称和路径硬编码,但是因为我有多个环境并且有时会创建新环境并且每个存储桶都附加了环境名称,所以我不想重写存储桶每次的名字。

例如,如果我在我的测试环境中,存储桶名称可能是 assetsxxxxxx-test 但如果我切换到新环境,我可能会引用 assetsyyyyy-dev 比方说。

事情是在 aswconfiguration.json 文件中引用了存储桶名称:

"S3TransferUtility": {
    "Default": {
        "Bucket": "assetsxxxxx-test",
        "Region": "us-east-2"
    }
}

所以我的问题是如何以编程方式引用该存储桶名称,以便在切换环境时重写该字段时,我不必更改我的代码。

谢谢

4

4 回答 4

1

我不清楚您使用什么来构建您的 Amplify 资源(cloudformation、terraform、?console?等),然后创建您的“aswconfiguration.json 文件”。但听起来您需要传入一个非常可实现的动态变量。

如果您使用代码管道、代码构建安排来部署资源和配置文件,您可以在代码构建阶段使用 bash 命令(sed 或 perl)来更改变量。或者使用自定义 lambda 更新文件内容并复制到 S3,然后将动态变量传递给环境变量参数。

通常,如果这是一个 cloudformation 模板,您可以使用 Pseudo Parameter Reference !Sub 命令,然后该参数将在早期声明并引用它的任何环境,例如

“桶”:“assetsxxxxxx-${Environment}”

于 2020-04-17T23:14:01.457 回答
1

我也有同样的问题。我的解决方案类似但不完全相同。首先,我像这样创建了 Codable 结构

import Foundation

struct AwsConfiguration: Codable {
    struct S3TransferUtility : Codable {
        private enum CodingKeys: String, CodingKey {
            case defaultConfig = "Default"
        }

        struct DefaultConfig : Codable {
            private enum CodingKeys: String, CodingKey {
                case bucket = "Bucket"
                case region = "Region"
            }
            var bucket: String
            var region: String
        }

        var defaultConfig: DefaultConfig
    }

    private enum CodingKeys: String, CodingKey {
        case s3TransferUtility = "S3TransferUtility"
    }

    var s3TransferUtility: S3TransferUtility
}

然后我定义了一个 DataHelper 类

final class DataHelper {
    static func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
        let data: Data

        guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
            else {
                fatalError("Couldn't find \(filename) in main bundle.")
        }

        do {
            data = try Data(contentsOf: file)
        } catch {
            fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
        }

        do {
            let decoder = JSONDecoder()
            return try decoder.decode(T.self, from: data)
        } catch {
            fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
        }
    }
}

然后放入awsconfiguration.json你的测试目标。然后你可以像这样写一个单元测试

    func testReadAWSConfiguration() throws {
        let config: AwsConfiguration = DataHelper.load("awsconfiguration.json")

        print ("************config bucket: \(config.s3TransferUtility.defaultConfig.bucket) " +
            "\n************config region: \(config.s3TransferUtility.defaultConfig.region)")
        XCTAssertNotEqual("", config.s3TransferUtility.defaultConfig.bucket)
        XCTAssertNotEqual("", config.s3TransferUtility.defaultConfig.region)
    }

于 2020-05-07T17:21:58.720 回答
0

我解决了。对于其他想知道的人,我仍然不确定 AWS 开发工具包中是否内置了一个字段,但我决定将 awsconfiguration.json 文件直接解析为自定义结构:

struct AWSConfigurationJSON: Codable{
    let S3TransferUtility: S3TransferUtility
}

struct S3TransferUtility: Codable{
    let Default: S3TransferUtilityDefault
}

struct S3TransferUtilityDefault: Codable{
    let Bucket: String
    let Region: String
}

然后我读取了文件并解析了 JSON。

if let path = Bundle.main.path(forResource: "awsconfiguration", ofType: "json") {
            do{
                let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
                let jsonResult = try JSONDecoder().decode(AWSConfigurationJSON.self, from: data)
                print(jsonResult.S3TransferUtility.Default.Bucket)
                bucketPath = jsonResult.S3TransferUtility.Default.Bucket
            }catch let e{
                print("error \(e)")
                bucketPath = ""

            }
        }else{
            bucketPath = ""

        }
于 2020-04-24T05:01:26.503 回答
0

您可以使用以下方式访问存储桶名称:

if let s3TransferInfo = AWSInfo.default().defaultServiceInfo("S3TransferUtility") {
    self.bucket = s3TransferInfo.infoDictionary["Bucket"] as? String
}

所以你不需要滚动你自己的配置的 JSON 解析

于 2021-11-10T02:41:28.700 回答