I have a NSTableview with three columns 'Thumbnail','FileName' and 'Datemodified'. The file name column and date modified column is filled with the output of S3ListObjectResponse. While the 'Thumbnail' column image is loaded from the local directory of the machine. If the file is missing, I download it from the S3 cloud. The problem is how to insert the data into the NSArrayController if the file is missing and I'm left with an empty cell for the thumbnail? Here is my work as of now :
- (IBAction)checkCloud:(id)sender {
AmazonS3Client *s3 = [AmazonClientManager s3];
S3ListObjectsRequest* listObjectsRequest = [[S3ListObjectsRequest alloc] initWithName:#"hello-testing"];
NSRange range = NSMakeRange(0, [[_fileListAC arrangedObjects] count]);
[_fileListAC removeObjectsAtArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:range]];
#try {
S3ListObjectsResponse* response = [s3 listObjects:listObjectsRequest];
NSMutableArray* objectSummaries = response.listObjectsResult.objectSummaries;
//looping through the objSummary and add into the NSArrayController
for ( S3ObjectSummary* objSummary in objectSummaries ) {
NSImage *thumbnail = [[NSImage alloc] init ];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *s3date = [dateFormatter dateFromString:[objSummary lastModified]];
NSArray *fileName = [[objSummary key] componentsSeparatedByString:#"/"];
if([[fileName objectAtIndex:0] localizedCaseInsensitiveCompare:#"Range"] == NSOrderedSame) {
NSLog(#"file name %# ",[fileName objectAtIndex:1]);
// Check for files in side the bucket's folders
if([[fileName objectAtIndex:1] length]){
NSString *thumbnailFile = [[fileName objectAtIndex:1] stringByAppendingString:#"_thumb.png"];
BOOL isDir;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePathPart1 = [#"/Users/" stringByAppendingString:[[NSHost currentHost] localizedName]];
NSString *filePath = [[[[ filePathPart1 stringByAppendingString:#"/Documents/Test/" ] stringByAppendingString:#"Range" ] stringByAppendingString:#"/Thumbnail/"] stringByAppendingString:thumbnailFile];
// If file exists then add into the thumbnail column
if([fileManager fileExistsAtPath:filePath isDirectory:&isDir]){
thumbnail = [[NSImage alloc] initWithContentsOfFile:filePath];
}else{
NSLog(#"file %# not found",thumbnailFile);
//Downloading from the S3 Cloud Asynchronously
doneDownload = NO;
AmazonS3Client *s3 = [AmazonClientManager s3];
S3GetObjectRequest *gor = nil;
#try {
gor = [[S3GetObjectRequest alloc] initWithKey:[[#"Range/Thumbnail/" stringByAppendingString:[fileName objectAtIndex:1]] stringByAppendingString: #"_thumb"] withBucket:#"thumbnail-pic" ];
gor.delegate = self;
[s3 getObject:gor];
}
#catch (AmazonClientException *exception) {
doneDownload = YES;
}
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!doneDownload);
gor.delegate = nil;
}
}else{
//If its the actual bucket folder and not file then load a default image
thumbnail = [NSImage imageNamed:#"Range.png"];
}
}
[_fileListAC addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:thumbnail,#"thumbnail", [objSummary key],#"Files",s3Date,#"Date Modified", nil]];
}
}
#catch (NSException *exception) {
NSLog(#"Cannot list S3 %#",exception);
}
//Display the table on loading the NSArrayController
[_cloudFileList makeKeyAndOrderFront:nil];
}
I have checked the delegate method
-(void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response{
NSData *imageData = [response body];
_coreDataImageView.image = [[NSImage alloc] initWithData:imageData];
doneDownload = YES;
}
coredataimageview is a test image well. The image is downloaded but I want to add it back to the array controller. Issue is what if I have 3 file missing from the local directory and I'm unable to insert into array controller for that file name and date modified values. Any help on this?
If you implement a delegate object (rather than using self) you could store these objects in an array and reference them later. The delegate object could track the additional pieces of metadata you are interested in and could be used to construct your table view.
Related
I am trying to upload large images to AWS S3 using the Multipart Upload API. From UI, i am sending the chunks(blob) of an image and when the last part arrives, completing the upload and getting the upload file url. It is working very nicely.
Sample Code:
public UploadPartResponse UploadChunk(Stream stream, string fileName, string uploadId, List<PartETag> eTags, int partNumber, bool lastPart)
{
stream.Position = 0;
//Step 1: build and send a multi upload request
if (partNumber == 1)
{
var initiateRequest = new InitiateMultipartUploadRequest
{
BucketName = _settings.Bucket,
Key = fileName
};
var initResponse = _s3Client.InitiateMultipartUpload(initiateRequest);
uploadId = initResponse.UploadId;
}
//Step 2: upload each chunk (this is run for every chunk unlike the other steps which are run once)
var uploadRequest = new UploadPartRequest
{
BucketName = _settings.Bucket,
Key = fileName,
UploadId = uploadId,
PartNumber = partNumber,
InputStream = stream,
IsLastPart = lastPart,
PartSize = stream.Length
};
var response = _s3Client.UploadPart(uploadRequest);
//Step 3: build and send the multipart complete request
if (lastPart)
{
eTags.Add(new PartETag
{
PartNumber = partNumber,
ETag = response.ETag
});
var completeRequest = new CompleteMultipartUploadRequest
{
BucketName = _settings.Bucket,
Key = fileName,
UploadId = uploadId,
PartETags = eTags
};
try
{
var res = _s3Client.CompleteMultipartUpload(completeRequest);
return res.Location;
}
catch
{
//do some logging and return null response
return null;
}
}
response.ResponseMetadata.Metadata["uploadid"] = uploadRequest.UploadId;
return response;
}
Now, i need to get the thumbnail of the uploaded image and upload that image too in a Thumbnails directory.
So basically, when the last part(chunk) arrives for the original image, i am completing the upload and retrieving the file url. At that time, i need to upload the thumbnail also and get back the thumbnail url.
I saw that people are referring of lambda function but don't know how to incorporate into my multipart api code setup.
Can anyone give me some direction here? Thanks in advance.
I am creating Sitecore item programtically and want to add some images for my item while creating programatically.It should get that image from Sitecore media, How to do that, need help.I Know how to do that using content item
If you only want to assign an image to a field you have to add this code:
item.Editing.BeginEdit();
ImageField imageField = item.Fields["Your Image Field"];
imageField.MediaID = new ID("IMAGE ID");
item.Editing.EndEdit();
If you want to create an image dynamically from a URL and then assign it to your item, you could use the following code:
var destinationPath = StringUtil.EnsurePostfix('/', imagesFolder.Paths.Path);
string imageName = ItemUtil.ProposeValidItemName(model.Title);
var options = new MediaCreatorOptions
{
Database = ItemHelpers.GetMasterDatabase(),
Versioned = false,
Destination = destinationPath + imageName,
FileBased = false,
IncludeExtensionInItemName = false,
KeepExisting = true,
AlternateText = imageName
};
try
{
WebClient cli = new WebClient();
byte[] imgBytes = cli.DownloadData(imageUrl);
using (var memStream = new MemoryStream(imageBytes))
{
Item scImage = MediaManager.Creator.CreateFromStream(memStream, imageUrl, options);
//Publish your Item
//scImage.ID is the one you need to assign to you image field
}
}
catch (Exception)
{
//Your code
}
I want to be able to create/update media items in code and also use language versioning. Here are more specifics. I have a Product content item. When that item is saved I want to be able to generate a PDF version of that item and save it to the media library. If the PDF version already exists in the media library I need to be able to update it. In addition this is a multi-language site. So if someone saves the French version of the Product content item I need to be able to generate the French version of the PDF and only save/update the French version of the associated PDF in the media library - not touch any of the other language versions of the PDF. I can't seem to figure out how to do this. The code that I have currently does the following: if I save the English version of the Product then it creates and English version of the PDF. But then if I save the French version of the Product, it creates a French version of the PDF and removes the English version of the PDF.
Anyone know how to do this?
public static Item AddMediaItem(byte[] fileBuffer, string fullMediaPath, string fileNameWithExtension, string title, Language language)
{
try
{
var db = Sitecore.Configuration.Factory.GetDatabase("master");
var options = new MediaCreatorOptions();
options.FileBased = false;
options.IncludeExtensionInItemName = false;
options.KeepExisting = false;
options.Versioned = true;
options.Destination = fullMediaPath;
options.Database = db;
options.Language = language;
var creator = new MediaCreator();
var fileStream = new MemoryStream(fileBuffer);
var pdfItem = db.GetItem(fullMediaPath, language);
if (pdfItem != null)
{
var updatedItem = creator.AttachStreamToMediaItem(fileStream, fullMediaPath, fileNameWithExtension,
options);
updatedItem.Editing.BeginEdit();
updatedItem.Fields["Title"].Value = title;
updatedItem.Editing.EndEdit();
return updatedItem;
}
else
{
//Create a new item
var newItem = creator.CreateFromStream(fileStream, fileNameWithExtension, options);
newItem.Editing.BeginEdit();
newItem.Fields["Title"].Value = title;
newItem.Editing.EndEdit();
return newItem;
}
}
catch (Exception ex)
{
return null;
}
}
Thanks to #JanBluemink for pointing me in the right direction. I found the right approach in the following article: Sitecore.Resources.Media.MediaCreator deletes versions of media. I just had to modify the code to use MediaManager instead of MediaCreator when updating.
public static Item AddMediaItem(byte[] fileBuffer, string fullMediaPath, string fileNameWithExtension, string title, Language language)
{
try
{
var db = Sitecore.Configuration.Factory.GetDatabase("master");
var options = new MediaCreatorOptions();
options.FileBased = false;
options.IncludeExtensionInItemName = false;
options.KeepExisting = false;
options.Versioned = true;
options.Destination = fullMediaPath;
options.Database = db;
options.Language = language;
var creator = new MediaCreator();
var fileStream = new MemoryStream(fileBuffer);
var pdfItem = db.GetItem(fullMediaPath, language);
if (pdfItem != null)
{
var mediaItem = new MediaItem(pdfItem);
var media = MediaManager.GetMedia(mediaItem);
media.SetStream(fileStream, "pdf");
pdfItem.Editing.BeginEdit();
pdfItem.Fields["Title"].Value = title;
pdfItem.Editing.EndEdit();
return pdfItem;
}
else
{
//Create a new item
var newItem = creator.CreateFromStream(fileStream, fileNameWithExtension, options);
newItem.Editing.BeginEdit();
newItem.Fields["Title"].Value = title;
newItem.Editing.EndEdit();
return newItem;
}
}
catch (Exception ex)
{
return null;
}
}
I had to add couple of more lines for updating media item stored in File System with versioning.
if (mediaItem.FileBased)
{
string uniqueFilename = FileUtil.GetUniqueFilename(FileUtil.MakePath(Settings.Media.FileFolder, MediaManager.Creator.GetMediaStorageFolder(mediaItem.ID, fileshortname)));
using (new Sitecore.SecurityModel.SecurityDisabler())
{
mediaItem.BeginEdit();
mediaItem.FilePath = uniqueFilename;
mediaItem.EndEdit();
}
}
Media media = MediaManager.GetMedia(mediaItem);
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
media.SetStream(stream, FileUtil.GetExtension(fileshortname));
}`
Sandbox Mode=on
Bundle ID =same FBid=Ok ..Anything else does not matter
-(void) askForPublishPermission
{ BOOL isSessionActive = [self isFacebookSessionActive];
//BOOL useUI = !isSessionActive;
//useUI = YES;
BOOL publishPermissionAvailable = NO;
if (isSessionActive)
{
NSArray* validPermission = [[FBSession activeSession] permissions];
for (int i=0; i<[validPermission count]; i++)
{
NSObject* permission = [validPermission objectAtIndex:i];
if ([permission isKindOfClass:[NSString class]])
{
NSString* validPermission = (NSString*)permission;
//NSLog(#"Valid Permissions = %#", validPermission);
if ([validPermission isEqualToString:#"publish_actions"])
{
publishPermissionAvailable = YES;
break;
}
}
}
}
if (publishPermissionAvailable == YES)
{
//NSLog(#"------------------ CALL AT TWO --------------");
//NSLog(#"Login Success");
}
else // Request for publish permission.
{
NSArray* permissionArray = [NSArray arrayWithObjects:
#"publish_actions",nil];
[FBSession openActiveSessionWithPublishPermissions:permissionArray
defaultAudience:FBSessionDefaultAudienceEveryone
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
}
and
-(void) askForPublishPermission
{
BOOL isSessionActive = [self isFacebookSessionActive];
//BOOL useUI = !isSessionActive;
//useUI = YES;
BOOL publishPermissionAvailable = NO;
if (isSessionActive)
{
NSArray* validPermission = [[FBSession activeSession] permissions];
for (int i=0; i<[validPermission count]; i++)
{
NSObject* permission = [validPermission objectAtIndex:i];
if ([permission isKindOfClass:[NSString class]])
{
NSString* validPermission = (NSString*)permission;
//NSLog(#"Valid Permissions = %#", validPermission);
if ([validPermission isEqualToString:#"publish_actions"])
{
publishPermissionAvailable = YES;
break;
}
}
}
}
if (publishPermissionAvailable == YES)
{
//NSLog(#"------------------ CALL AT TWO --------------");
//NSLog(#"Login Success");
}
else // Request for publish permission.
{
NSArray* permissionArray = [NSArray arrayWithObjects:
#"publish_actions",nil];
[FBSession openActiveSessionWithPublishPermissions:permissionArray
defaultAudience:FBSessionDefaultAudienceEveryone
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
}
But ..Not login..
error code see below:
Error = Error Domain=com.facebook.sdk Code=2 "The operation couldn’t be completed. (com.facebook.sdk error 2.){com.facebook.sdk:ErrorLoginFailedReason=com.facebook.sdk:SystemLoginCancelled, com.facebook.sdk:ErrorInnerErrorKey=Error Domain=com.apple.accounts Code=7 "The Facebook server could not fulfill this access request: The app must ask for a basic read permission like email at install time."
I'd spent a few months this issue..Please Help me
Your error message says:
The app must ask for a basic read permission like email at install time.
From the docs:
When someone connects with an app using Facebook login, the app can access their public profile and friend list, the pieces of information that are visible to everyone. To create this basic connection, apps must always request access to a person's basic profile information by asking for the basic_info permission.
Try adding basic_info to permissionArray array. If that doesn't work, try adding email as well.
I replaced :
[FBSession openActiveSessionWithPublishPermissions:#[#"publish_actions"] defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:stateHandler];
with
[FBSession openActiveSessionWithPublishPermissions:#[#"basic_info", #"publish_actions", #"email"] defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:stateHandler];
And now it's working
(permissions orders matter, basic_info have to be in first position)
I want to connect with a web service from my iOS app. Previously my URL was http://<domain name>/mobilews/mobilews.asmx. Recently I changed to http://<domain name>/mobilewstest/mobilews.asmx
I have put my URL in info plist file. But after I changed this into new URL I cannot login to that.
NSString *urlString = [NSString stringWithFormat:#"%#%#",serverURL,[queryString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
NSHTTPURLResponse *response ;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
int statusCode = [((NSHTTPURLResponse *)response) statusCode];`
Here returnData become nill and statusCode is 0. But this urlString is successfully logged in to the web service when it gives in the browser.
NSURL *url = [NSURL URLWithString:#"YOUR URL HERE"];
NSError *connectionError = nil;
NSData *inData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&connectionError];
NSInteger code = [connectionError code];
if (code != 0)
{
NSString *locDesc = [NSString stringWithString:[connectionError localizedDescription]];
NSString *locFail = [NSString stringWithString:[connectionError localizedFailureReason]];
NSLog(#"Error: %d %# %#", code, locDesc, locFail);
}
else if ([inData length] == 0)
{
NSLog(#"No data");
}
else{
NSData *resultData = [NSData dataWithContentsOfURL:url];
NSString *responseString = [[NSString alloc]initWithData:resultData encoding:NSUTF8StringEncoding];
}
I see you send a syncronous request... try this its more an easy approach.