package co.smartreceipts.android.aws.s3; import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import com.google.common.base.Preconditions; import java.io.File; import javax.inject.Inject; import co.smartreceipts.android.aws.cognito.CognitoManager; import co.smartreceipts.android.di.scopes.ApplicationScope; import co.smartreceipts.android.utils.log.Logger; import io.reactivex.Observable; @ApplicationScope public class S3Manager { private static final String BUCKET = "smartreceipts"; private final S3ClientFactory s3ClientFactory; private final S3KeyGeneratorFactory s3KeyGeneratorFactory; @Inject public S3Manager(Context context, CognitoManager cognitoManager) { this(new S3ClientFactory(context, cognitoManager), new S3KeyGeneratorFactory()); } @VisibleForTesting S3Manager(@NonNull S3ClientFactory s3ClientFactory, @NonNull S3KeyGeneratorFactory s3KeyGeneratorFactory) { this.s3ClientFactory = Preconditions.checkNotNull(s3ClientFactory); this.s3KeyGeneratorFactory = Preconditions.checkNotNull(s3KeyGeneratorFactory); } /** * Uploads a file to this user's S3 cognito account * * @param file the {@link File} to upload * @param subDirectoryPath the subdirectory path to load to (either an empty string for the bucket or something more complex as desired) * @return an {@link Observable} that will return the URL path as a string if valid */ @NonNull public Observable<String> upload(@NonNull final File file, @NonNull final String subDirectoryPath) { return s3ClientFactory.getAmazonS3() .flatMap(amazonS3 -> { if (amazonS3.isPresent()) { return s3KeyGeneratorFactory.get() .flatMap(s3KeyGenerator -> Observable.create(emitter -> { try { final String key = subDirectoryPath + s3KeyGenerator.getS3Key() + file.getName(); amazonS3.get().putObject(BUCKET, key, file); emitter.onNext(amazonS3.get().getResourceUrl(BUCKET, key)); emitter.onComplete(); } catch (Exception e) { Logger.error(S3Manager.this, "Failed to upload to S3 with error.", e); emitter.onError(e); } })); } else { return Observable.error(new Exception("Failed to initialize the S3 client")); } }); } }