How to upload app package contents to AWS S3 - ios

I use AWS SDK iOS v2.8.2 to upload and download files to AWS S3 and it works great with the exception of application packages (.app). As these packages are basically layers of sub-folders that's how I have been uploading and downloading them, but the .app files are corrupted or damaged when I try to run them (after upload or download). This is how I download a file from AWS S3 (upload is the same except I have defined contenType as well):
NSURL *downloadedLocationURL=[NSURL fileURLWithPath:downloadedLocationstring];
NSFileManager *fileManager= [NSFileManager defaultManager];
[fileManager createDirectoryAtPath: [downloadedLocationURL.URLByDeletingLastPathComponent path]
withIntermediateDirectories:YES
attributes:nil
error:NULL];
self.transferUtility = [AWSS3TransferUtility S3TransferUtilityForKey:currentBucket.regionShortName];
[self.transferUtility downloadToURL:downloadedLocationURL
bucket:bucket.name
key:key
expression:expression
completionHandler:completionHandler]
I realized that I need to upload the package in a different way but I am not sure how to. Should I define the contentType in any way? Should I rather compress any package content and upload as a .zip file? Most other file formats seem to function correctly so I wonder what is the trick with app packages may be that I am unable to see.
Thanks for your help.

Have you confirmed through AWS S3 console that the uploaded object is as you expect it to be?
You can directly download the file from the AWS console and reference it back where you need it to first ensure that the upload was done correctly. My other guess is to do with playing around with setting the content-type on your upload.

Related

iCloud file versions and mystery files

I have been trying to retrofit a large app to have it store its files in iCloud. The app is not really "Document-based" but the files may be thought of as configuration or preference files.
To be honest I haven't followed all the Apple iCloud guidelines. Some really don't fit in with the flow of the app. When the app starts I read the files from the ubiquity directory (using normal file reads) and when I write them I use a normal file write to the ubiquity directory. When the app start, I also call:
[fileManager startDownloadingUbiquitousItemAtURL:url error:&error];
I do have an NSFilePresenter watching for changes in the ubiquity directory. It notifies me of file changes but there are never any conflict notifications.
My problem is that often when I upload a file to iCloud, it will create a separate file with a number appended. E.g.
MyFile.skyset
MyFile 2 .skyset
These seem to show up when more than one app has been writing MyFile.skyset to the ubiquity directory.
They don't seem to be conflicted file versions. If I use NSFileVersion to look for conflicts and other versions, I only see the one version of MyFile.skyset and it is not in conflict.
I can't find any documentation that explains what this "versioned" file is and what to do about it. Any thoughts as to what is going on here?
Well, I don't fully understand the "versions" but the problem was solved by changing how I updated the files in the ubiquity directory.
I changed from:
[fileMgr removeItemAtPath:dstPath error:nil];
[fileMgr copyItemAtPath:srcPath toPath:dstPath error:&error];
To:
NSData *data = [NSData dataWithContentsOfFile:srcPath];
[data writeToFile:dstPath atomically:NO];
I looks like the operation of deleting the file before copying the updated information to the ubiquity directory was confusing the system. After switching to the second form I'm no longer seeing this problem.
Hope this answer helps someone else.

Replace Data Container of an iOS .ipa File

I have an app that downloads a whole bunch of data from over 100+ APIs upon successful login. I successfully download the data, and then use iExplorer to extract the data container folders (Documents, Library and Tmp) from the fully loaded application.
I would like to take a blank version of the original app, in .ipa format, and insert those data container folders into that fully loaded .ipa file. Then I will be able to take this new fully loaded .ipa, and use a deployment software to deploy it to a bunch of local user's devices. So everyone will have this fully loaded app.
Please, has anyone done this? Please provide some feedback, and don't argue with my methodology, because this has be done this way due to requirements. Maybe there is a step I'm missing? I'm not sure.
With the source code in hand, you can run the app in the simulator (no need for iExplorer), wait for it to download all the files and browse to the folder on your computer where the app was installed.
From there you can put aside any files you want along with their respective folders. If you're using Coredata there should be a SQLITE database file there somewhere (typically in your Application Support folder) and this might be all you need but it is hard to tell without looking at your implementation details.
Once you have the files you need set aside, add them to the app bundle via Xcode and create code to check whether files already exist (in which case you don't want to replace them), and if not copy all files needed from the bundle into their respective folders.
Here's some semi pseudo-code for you:
NSDictionary *userPrefs = [[NSUserDefaults standardUserDefaults] objectForKey:self.email];
if (![userPrefs[kInitialSetupCompleted] boolValue])
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *destinationFilePath = ...
NSURL *seedFilePath = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:kCoreDataStoreName ofType:nil]];
NSError* err = nil;
if (![fileManager copyItemAtURL:seedPath toURL:destinationFilePath error:&err]) {
NSLog(#"Could not copy seed data. error: %#", err);
// Deal with error
} else {
// Set user defaults kInitialSetupCompleted to YES
}
}

Change file name in UIDocumentInteractionController when opening file in another app

I'm storing files in my application sandbox in a way that masks the original name of the file.
For example I have a file called abc.png which is stored in the sandbox as obfuscated.png.
When I do an open in of this file in another application using a UIDocumentInteractionController I'd like to have the other file open the file with the filename abc.png
Currently the other app opens the file as obfuscated.png.
I have tried changing the name property of the UIDocumentInteractionController in documentInteractionControllerWillPresentOptionsMenu as well as willBeginSendingToApplication, however in both cases the receiving application does not get the correct filename - it continues to show the obfuscated filename.
Apart from creating a copy of the file with the unobfuscated name, is there a way to make the receiving application use the desired filename?
Instead of a copy try:
NSError *error = nil;
[[NSFileManager defaultManager] linkItemAtPath:obfuscatedFilePath toPath:abcFilePath error:&error];
This will create a hard link to the file. Symbolic links will not work.

Copy iCloud file to sandbox

I'm looking for a better way to download a bunch of files from my iCloud container to my sandbox. This is what I currently use:
for (FileAttachments *fileLink in items) {
NSURL *cloudFileURL = [fileLink urlForCloudAttachmentWithName];
NSURL *fileURL = [backupCloudLocalDirectoryURL URLByAppendingPathComponent: fileLink.fileName];
NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateReadingItemAtURL:fileURL options:NSFileCoordinatorReadingWithoutChanges error:&error
byAccessor:^(NSURL *newURL) {
NSError *blockError = nil;
[fileManager copyItemAtURL:cloudFileURL toURL:fileURL error:&blockError];
}];
}
}
Is there any problem with making a copy of the iCloud item this way? In production, I have some users complaining that all their files weren't downloaded. Is it better to use NSFileManager's startDownloadingUbiquitousItemAtURL:error instead? If so, why?
Thanks.
It's still not completely clear to me from comments how you're discovering the URLs, however some important details that affect your situation are:
Using coordinateReadingItemAtURL:block: has nothing to do with downloading files from iCloud. The purpose of NSFileCoordinator is to coordinate among readers and writers of a file so that, for example, you don't get two threads trying to write to the same file at the same time. You use file coordinators with iCloud because the iCloud system needs to read and write files and so does your app. Using a coordinator avoids corrupting the file, but again, has nothing to do with downloading the file.
To download a file from iCloud you need to use startDownloadingUbiquitousItemAtURL:error: and then wait until the file downloads. The normal flow here is:
a. Use NSMetadataQuery to find files that exist in the iCloud account
b. Use startDownloadingUbiquitousItemAtURL:error: to make sure they're available on the local device.
The reason you need to use this call is simply because that's how iCloud works on iOS. Files don't download until you ask them to download, and this is how you ask. [On OS X it's different, everything automatically downloads.]
You cannot simply copy from an iCloud URL to another location unless you already know that the file has been downloaded. The file-copy operation does not download the file, so if the file isn't available locally, the copy will fail.
You must use a metadata query to identify the files and their download status then, if they have not been downloaded initiate the download, and using the metadata query determine when the download is complete and then copy the file from the ubiquity container to the apps sandbox directory using a file coordinator. If you try copying the file while it's partially downloaded you may get some strange results.
I had the same problem with you.
My case is that: When network disconnects, iCloud service copy file from iCloud container to sandbox. When this line executes, it can not go into the block to copy file. This is the reason why this file can not be copied.
fileCoordinator coordinateReadingItemAtURL:fileURL options:NSFileCoordinatorReadingWithoutChanges error:&error byAccessor:^(NSURL *newURL)
My solution is: Before copying file from iCLoud container to sandbox, you must check network. If it is not available, don't execute this code (return method). If network connects, execute fileCoordinator and copy.
More info: When copy file from ICloud container to sandbox, method fileManager copyItemAtURL:toURL:error: is OK because I implement this method and it's good.
Hope this works.

office documents won't open with quicklook

I've created 2 test applications:
In the one the documents are included into the bundle and can be opened by using the quick look controller.
In the other app, the documents are downloaded. When I try to open the files the quick-look controller simply shows a message saying an error occurred. Strangely it will open downloaded PDF documents without any problems.
I suspect it has something to do with headers and mime-types, but I'm not sure on this. Would anyone know what the reason could be that downloaded .doc or .docx documents won't open and local documents will?
It turned out to be a problem with saving the downloaded files. At first I was writing the data to a filepath URL. This saved the data to the right location, but the type of file wasn't recognized anymore.
The solution was to use the default FileManager to save the file.
[[NSFileManager defaultManager] createFileAtPath:filePath contents:data attributes:nil];

Resources