0

I'm trying to upload a video from an iOS device's library to AWS.

I have a method called uploadVideo that gets passed an ALAsset asset which I then try to upload as follows:

- (void)uploadVideo:(ALAsset *)asset :(UIImage*)image{
    AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];
    AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
    uploadRequest.bucket = @"test";
    NSString *assetFilename = [[asset defaultRepresentation] filename];
    if(!assetFilename){
        NSDate *now = [NSDate date];
        NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
        [dateFormat setDateFormat:@"MM-dd-yyyy_HH-mm-ss-SS"];
        assetFilename = [dateFormat stringFromDate:now];
    }
    uploadRequest.key = assetFilename;
    uploadRequest.body = asset.defaultRepresentation.url.absoluteURL;
    NSLog(@"uploadRequest.body: %@", asset.defaultRepresentation.url.absoluteString);

    [[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor]
           withBlock:^id(AWSTask *task) {
               if (task.error) {
                   if ([task.error.domain isEqualToString:AWSS3TransferManagerErrorDomain]) {
                       switch (task.error.code) {
                           case AWSS3TransferManagerErrorCancelled:
                           case AWSS3TransferManagerErrorPaused:
                               break;

                           default:
                               NSLog(@"Error: %@", task.error);
                               break;
                       }
                   } else {
                       // Unknown error.
                       NSLog(@"Error: %@", task.error);
                   }
               }

               if (task.result) {
                   AWSS3TransferManagerUploadOutput *uploadOutput = task.result;
                   // The file uploaded successfully.
                   NSLog(@"uploaded the file to aws successfully with task result %@", task.result);
               }
               return nil;
       }];
}

I am receiving the error:

Error: Error Domain=NSCocoaErrorDomain Code=260 "The operation couldn’t be completed. (Cocoa error 260.)" UserInfo=0x1706686c0 {NSFilePath=/asset.mp4, NSUnderlyingError=0x170256170 "The operation couldn’t be completed. No such file or directory"}

But when I log the uploadRequest.body path, it seems to be the full path:

uploadRequest.body: assets-library://asset/asset.mp4?id=01DD578D-6320-430E-BAB4-F339B3EB4D5C&ext=mp4

How do I properly set the body of a selected asset to upload to AWS?

Edit: It looks like you can't upload an ALAsset directly to AWS. To try to resolve this issue, I tried saving a temporary video file (as described in Getting video from ALAsset), but I'm still running into problems. I get the error that no file exists at the created path. Here is my code:

 NSString *vidTmpPath = [self videoAssetURLToTempFile:asset.defaultRepresentation.url];
    NSLog(@"vidTmpPath: %@", vidTmpPath);

    if ([[NSFileManager defaultManager] fileExistsAtPath:vidTmpPath])
    {
        NSLog(@"video file exists at path");
    }else{
        NSLog(@"no video exists at path");
    }

    uploadRequest.body = [NSURL URLWithString: vidTmpPath];

And the videoAssetURLToTempFile method:

-(NSString*) videoAssetURLToTempFile:(NSURL*)url
{
    NSLog(@"in videoAssetURLToTempFile");
    NSString * surl = [url absoluteString];
    NSString * ext = [surl substringFromIndex:[surl rangeOfString:@"ext="].location + 4];
    NSTimeInterval ti = [[NSDate date]timeIntervalSinceReferenceDate];
    NSString * filename = [NSString stringWithFormat: @"%f.%@",ti,ext];
    NSString * tmpfile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];

    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
    {

        ALAssetRepresentation * rep = [myasset defaultRepresentation];

        NSUInteger size = [rep size];
        const int bufferSize = 8192;

        NSLog(@"Writing to %@",tmpfile);
        FILE* f = fopen([tmpfile cStringUsingEncoding:1], "wb+");
        if (f == NULL) {
            NSLog(@"Can not create tmp file.");
            return;
        }

        Byte * buffer = (Byte*)malloc(bufferSize);
        int read = 0, offset = 0, written = 0;
        NSError* err;
        if (size != 0) {
            do {
                read = [rep getBytes:buffer
                          fromOffset:offset
                              length:bufferSize
                               error:&err];
                written = fwrite(buffer, sizeof(char), read, f);
                offset += read;
            } while (read != 0);


        }
        fclose(f);


    };


    ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
    {
        NSLog(@"Can not get asset - %@",[myerror localizedDescription]);

    };

    if(url)
    {
        NSLog(@"saving at url: %@", url);
        ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
        [assetslibrary assetForURL:url
                       resultBlock:resultblock
                      failureBlock:failureblock];
    }

    return tmpfile;
}
Community
  • 1
  • 1
scientiffic
  • 9,045
  • 18
  • 76
  • 149
  • Perhaps try saving the ALAsset in a temporary folder and uploading that copy? Only other thing I can think of is the assets library went away...? – shilmista Jul 02 '15 at 17:01
  • hm, well the ALAsset already exists, so it seems unnecessary to save a copy. perhaps I am passing the path of the asset incorrectly? – scientiffic Jul 02 '15 at 17:03
  • 1
    https://github.com/aws/aws-sdk-ios/issues/121 It appears ALAsset upload isn't currently supported. Yeah it's a little extraneous to copy the data again but it doesn't seem to read those URLs correctly – shilmista Jul 02 '15 at 17:07
  • @shilmista thanks for sharing the link. I tried saving a temporary file before uploading to AWS and am still getting errors that the file doesn't exist. Any ideas? – scientiffic Jul 02 '15 at 17:53
  • 1
    Could be a timing issue, you're returning the tmpfile pretty much immediately and the resultblock is asynchronous so it won't finish by the time you check that directory. – shilmista Jul 02 '15 at 18:05
  • if you add your second comment (the one that links to the github issue), I'll mark it as correct. – scientiffic Jul 02 '15 at 20:08

0 Answers0