最近公司需要把图片上传从华为云改成亚马逊云,记录一下操作流程,最早亚马逊云是使用AWS的库来进行上传,但是最近亚马逊使用了Amplify方式(Swift语言)上传。特此记录一下基本的操作方式
首先,必须安装 Amplify CLI,先确认本机是否已经安装 nodejs,npm 然后打开终端 输入以下连接完成 Amplify CLI安装,
curl -sL https://aws-amplify.github.io/amplify-cli/install | bash && $SHELL
接下来打开终端,路径设置到工程目录下,运行 Amplify init 命令进行初始化
创建完成后,会在控制上 IAM-角色-生成两个角色(点击这2个角色分别给他们添加S3Full的权限),还有在S3的桶上自动生成一个桶(如果要用运维给的桶,可以删除自动生成的桶)。
工程会新增2个json文件
目前还不能使用,接着要开始引入桶,再次打开终端,输入amplify import storage,选择S3 Bucket
然后 Add auth,添加一个用户池,选择第一个默认 Default configuration.完成用户池的创建
接着会出现bucket,选择运维给你的那个就完成创建
完成创建后会提示已经创建完成,接着再次打开终端 输入 amplify push 把配置上传到服务器
上传完成后,在后台点击左上角选择Cognito进入用户池及身份验证,就会看到自己创建的用户池及联合身份
然后两个json文件也会出现变化。
接着点击身份池上身份,然后点击右上角编辑身份池,把启用未经验证的身份的访问权限勾上
然后记住自己未经身份验证的角色的名称,接着去控制台的主页选择IAM-角色-点击刚才记住的那个名称,给它添加权限(如果需要用户登录的就给另一个也添加权限)。一般给个S3Full的权限就行
至此,亚马逊的操作就差不多了。
接下来是工程方面的操作。
如果是纯OC的,可以参考https://github.com/awslabs/aws-sdk-ios-samples
以下是Swift语言的版本,(同时兼容OC环境)
在pod上导入相关的库
pod 'Amplify'
pod 'Amplify/Tools'
pod 'AmplifyPlugins/AWSS3StoragePlugin'
pod 'AmplifyPlugins/AWSCognitoAuthPlugin'
然后打开工程会看到相应的配置文件
接着开始写初始化流程,也可以参照他们官方的文档 https://docs.amplify.aws/lib/q/platform/ios/
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
//初始化流程
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.APSoutheast1,
identityPoolId:"ap-southeast-1:a5f09d6d-e4a5-4997-8f3e-1d388de90abc")
let configuration = AWSServiceConfiguration(region:.APSoutheast1, credentialsProvider:credentialsProvider)
try Amplify.add(plugin: AWSCognitoAuthPlugin())
try Amplify.add(plugin: AWSS3StoragePlugin())
try Amplify.configure()
return true
}
然后是注册与登录,如果不需要登录的话,就不需要这2步操作
//注册流程
func signUp(username: String, password: String, email: String) {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
Amplify.Auth.signUp(username: username, password: password, options: options) { result in
switch result {
case .success(let signUpResult):
if case let .confirmUser(deliveryDetails, _) = signUpResult.nextStep {
print("Delivery details \(String(describing: deliveryDetails))")
} else {
print("SignUp Complete")
}
case .failure(let error):
print("An error occurred while registering a user \(error)")
}
}
}
//登录流程
func signIn(username: String, password: String, email: String) {
// Amplify.Auth.signOut()
Amplify.Auth.signIn(username: username, password: password) { result in
switch result {
case .success:
print("Sign in succeeded")
case .failure(let error):
print("Sign in failed \(error)")
}
}
}
然后是上传下载的流程
//下载流程
func download(name:String){
let downloadToFileName = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask)[0]
.appendingPathComponent(name)
Amplify.Storage.downloadFile(
key: name,
local: downloadToFileName,
progressListener: { progress in
print("Progress: \(progress)")
}, resultListener: { event in
switch event {
case .success:
print("Completed")
case .failure(let storageError):
print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
}
})
}
//上传流程,我这边是改成数组上传
func uploadData(images:NSArray,index:Int){
let timeInterval:NSInteger = NSInteger(NSDate.init().timeIntervalSince1970)
let theFinal = timeInterval
let stringName = String(format: "path%d.jpg", theFinal)
let imgGet:UIImage = images.object(at: index) as! UIImage
let data = imgGet.jpegData(compressionQuality: 0.5)
//
let options = StorageUploadDataRequest.Options(accessLevel: .guest)
Amplify.Storage.uploadData(key: stringName, data: data!, options: options) { progress in
print("Progress: \(progress)")
} resultListener: { event in
switch event {
case .success(let data):
if index != images.count-1 {
uploadData(images: images, index: index+1)
}else{
print("Completed: \(data)")
}
case .failure(let storageError):
print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
}
}
}
我这里写了一个OC调用Swift的版本,仅供参考,上传的状态可以使用kvo对isUploadImageDone进行监听
import Amplify
import AmplifyPlugins
import AWSCognitoIdentityProvider
//使用单例进行初始化
@objc class UploadImageAmazon: NSObject {
@objc dynamic var isUploadImageDone:Bool = false
@objc var aryImages:NSMutableArray = NSMutableArray()
@objc static let staticInstance = UploadImageAmazon()
@objc static func sharedInstance() -> UploadImageAmazon{
return staticInstance
}
private override init(){
do {
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.APSoutheast1,
identityPoolId:"ap-southeast-1:84207a2d-de78-45e2-bb6c-fd1c214c6f17")
let configuration = AWSServiceConfiguration(region:.APSoutheast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
try Amplify.add(plugin: AWSCognitoAuthPlugin())
try Amplify.add(plugin: AWSS3StoragePlugin())
try Amplify.configure()
print("Amplify configured with storage plugin")
} catch {
print("Failed to initialize Amplify with \(error)")
}
}
func signUp(username: String, password: String, email: String) {
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
Amplify.Auth.signUp(username: username, password: password, options: options) { result in
switch result {
case .success(let signUpResult):
if case let .confirmUser(deliveryDetails, _) = signUpResult.nextStep {
print("Delivery details \(String(describing: deliveryDetails))")
} else {
print("SignUp Complete")
}
case .failure(let error):
print("An error occurred while registering a user \(error)")
}
}
}
func signIn(username: String, password: String, email: String) {
// Amplify.Auth.signOut()
Amplify.Auth.signIn(username: username, password: password) { result in
switch result {
case .success:
print("Sign in succeeded")
case .failure(let error):
print("Sign in failed \(error)")
}
}
}
@objc func uploadData(images:NSArray,index:Int,userid:NSInteger){
let timeInterval:NSInteger = NSInteger(NSDate.init().timeIntervalSince1970)
let theFinal = timeInterval + userid
let stringName = String(format: "feedback/%d.jpg", theFinal)
let imgGet:UIImage = images.object(at: index) as! UIImage
let data = imgGet.jpegData(compressionQuality: 0.5)
Amplify.Storage.uploadData(key:stringName, data: data!,
progressListener: { progress in
print("Progress: \(progress)")
}, resultListener: { (event) in
switch event {
case .success(let data):
if index != images.count-1 {
self.isUploadImageDone = false
let next = index + 1
self.aryImages.add("public/".appending(stringName))
self.uploadData(images: images, index: next,userid: userid)
}else{
self.aryImages.add("public/".appending(stringName))
self.isUploadImageDone = true
}
print("Completed: \(data)")
case .failure(let storageError):
print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
}
})
}
@objc func download(imagePath:String){
let downloadToFileName = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask)[0]
.appendingPathComponent(imagePath)
Amplify.Storage.downloadFile(
key: imagePath,
local: downloadToFileName,
progressListener: { progress in
print("Progress: \(progress)")
}, resultListener: { event in
switch event {
case .success:
print("Completed")
case .failure(let storageError):
print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
}
})
}
}
以上就是亚马逊云上传图片的基本流程,但是目前有个奇怪的问题,不管是登录还是未登录用户,上传的图片都只能放到public文件夹上,这个问题期待后续能解决,还有如果要删除亚马逊云的配置,不能简单的删除,必须要使用命令,打开终端,输入amplify delete 来进行删除才能删除彻底,不然会在IAM-角色里多了很多没用的角色