Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloud Storage services, what, how and which?

In some ways I guess you could say I'm creating something similar to the iOS app 'Vine'. A social network letting users upload videos for others to watch. My entire project is pretty much ready, I'm using a database service called Parse, but there's not much storage there, and if you want to scale it up, it gets pricey. I have figured I can use the database I already have, and having the sql-table for "Videos" have an URL-column linking to the actual video file. I have been looking for data storage services, and found Google's 'Cloud Storage'.

What I'm really looking for, if possible, is something like this use case:

  1. Client app has a video ready to upload.
  2. Uploads video-file to some-cloud-service.com/myCompany/videoNameID.mp4
  3. Store this URL in the URL-field of a 'video-object' in the database.
  4. When other users are fetching a list of videos, they get a collection of names and URLs
  5. When the user wants to play a certain video, fetch it from the URL in the table.

I have been thinking I can use cloud storage as a place to upload and access files for my app. I've been looking through the API and documentation for Google's Cloud Storage, but there's so much in there I have no use for, and I don't understand most of it. I'm starting to think "Cloud Storage" isn't what I think it is. I simply need a place to upload potentially huge amounts of large files, directly from an iOS-app (and website later). The data storage service Parse offers is perfect, but very limited in size. I know it has the potential of getting expensive. From reading the prices of this google service, it looked both cheap and exactly what I need, but I can't understand how, if possible, I should use it to directly upload a file using my "credentials", and receiving an URL in return for where the file ended up.

Can I use Google's Cloud Storage for this? Or something else? Or have I completely misunderstood how to use Cloud Storage?

like image 925
Sti Avatar asked Aug 17 '13 21:08

Sti


2 Answers

Actually, the Objective-C wrapper library for the Google services has quite detailed documentation here: https://code.google.com/p/google-api-objectivec-client/wiki/Introduction#Preparing_to_Use_the_Library

It tells you that this wrapper library is generated automatically based on the underlying JSON APIs. So all the GTLStorage... classes will mimic the JSON API for Google Storage. The class for performing the actual API calls is GTLQueryStorage.

If you look at that JSON documentation, you'll find that there is a class Objects that is used to store data into buckets: https://developers.google.com/storage/docs/json_api/v1/#Objects The method to upload a new object is 'insert'

Back at the GTLQueryStorage.h file, you'll find the corresponding Objective-C method to insert a new object into your bucket:

// Method: storage.objects.insert
// Stores new data blobs and associated metadata.
//  Required:
//   bucket: Name of the bucket in which to store the new object. Overrides the
//     provided object metadata's bucket value, if any.
//  Optional:
//   ifGenerationMatch: Makes the operation conditional on whether the object's
//     current generation matches the given value.
//   ifGenerationNotMatch: Makes the operation conditional on whether the
//     object's current generation does not match the given value.
//   ifMetagenerationMatch: Makes the operation conditional on whether the
//     object's current metageneration matches the given value.
//   ifMetagenerationNotMatch: Makes the operation conditional on whether the 
//     object's current metageneration does not match the given value.
//   name: Name of the object. Required when the object metadata is not
//     otherwise provided. Overrides the object metadata's name value, if any.
//   projection: Set of properties to return. Defaults to noAcl, unless the
//     object resource specifies the acl property, when it defaults to full.
//      kGTLStorageProjectionFull: Include all properties.
//      kGTLStorageProjectionNoAcl: Omit the acl property.
//  Upload Parameters:
//   Accepted MIME type(s): */*
//  Authorization scope(s):
//   kGTLAuthScopeStorageDevstorageFullControl
//   kGTLAuthScopeStorageDevstorageReadWrite
// Fetches a GTLStorageObject.
+ (id)queryForObjectsInsertWithObject:(GTLStorageObject *)object
                           bucket:(NSString *)bucket
                 uploadParameters:(GTLUploadParameters *)uploadParametersOrNil;

So you should:

  • Allocate an instance of GTLServiceStorage
  • Set your API key to that object
  • Instantiate a GTLQueryStorage object using the class method above for the object you want to save with the right bucket
  • Create a Service Ticket which performs the query and gets a completion handler to handle the completion (success, error cases).
like image 102
dirkgroten Avatar answered Nov 21 '22 22:11

dirkgroten


late response, but this may help others with this issue. this code uploads a video to GCS (tested and working)

Authentication first

this will pop the Google authentication view controller (you have to add "GTMOAuth2ViewTouch.xib" file to your project).

- (void) uploadVideoToGoogleCloud {

// declare this
//@property (strong, nonatomic) GTLServiceStorage* serviceStorage;
//@property (strong, nonatomic) NSString* accessToken;

_serviceStorage = [[GTLServiceStorage alloc] init];
_serviceStorage = [GTLServiceStorage new];
_serviceStorage.additionalHTTPHeaders = @{@"x-goog-project-id": @"yourGoogleProjectId"};

// authenticate
GTMOAuth2ViewControllerTouch *oAuthVC =
[[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeStorageDevstorageReadWrite
                                           clientID:@"yourClientId from Client ID for iOS application"
                                       clientSecret:@"yourSecret from Client ID for iOS application"
                                   keychainItemName:@"use nil or give a name to save in keychain"
                                  completionHandler:^(GTMOAuth2ViewControllerTouch *viewController, GTMOAuth2Authentication *auth, NSError *error) {

                                      _accessToken = [NSString stringWithFormat:@"Bearer %@", [auth.parameters objectForKey:@"access_token"]];

                                      _serviceStorage.additionalHTTPHeaders = @{@"x-goog-project-id": kProjectID, @"Content-Type": @"application/json-rpc", @"Accept": @"application/json-rpc", @"Authorization": _accessToken};

                                      _serviceStorage.authorizer = auth;


                                      dispatch_async(dispatch_get_main_queue(), ^{
                                          [self dismissViewControllerAnimated:YES completion:nil];
                                      });
                                  }];


dispatch_async(dispatch_get_main_queue(), ^{
    [self presentViewController:oAuthVC animated:YES completion:nil];
});
}

Upload Video after authentication

after user has authenticated successfully, call this to upload the video

// upload video file
NSString *filename = @"yourVideoFileNameNoExtension";
NSString *pathToMovie = [[NSBundle mainBundle] pathForResource:filename ofType:@".mp4"];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:pathToMovie];
if (fileHandle) {

    GTLUploadParameters *uploadParam =
    [GTLUploadParameters uploadParametersWithFileHandle:fileHandle MIMEType:@"video/mp4"];

    GTLStorageObject *storageObj = [GTLStorageObject object];
    storageObj.name = @"thisWillAppearOnTheBucketAsTheFilename";

    GTLQueryStorage *query = [GTLQueryStorage queryForObjectsInsertWithObject:storageObj bucket:@"your-bucket-name" uploadParameters:uploadParam];

    GTLServiceTicket *ticket = [_serviceStorage executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
        NSLog(@"error:%@", error ? [error description] : @"query succeeded!");
    }];


    ticket.uploadProgressBlock = ^(GTLServiceTicket *ticket,
                                   unsigned long long numberOfBytesRead,
                                   unsigned long long dataLength) {
        NSLog(@"ticket: %@", ticket);
        NSLog(@"read %llu from %llu bytes", numberOfBytesRead, dataLength);
    };

} else {
    NSLog(@"no video file handle!");
}

hope this helps :)

like image 27
lilush Avatar answered Nov 21 '22 21:11

lilush