-->

XMPPFramework - Upload Profile or Avatar Image

2020-07-13 10:49发布

问题:

I am working on the chat app in which I have used the xmpp framework. I am able to send or receive the messages through xmpp. But when I tried to upload the user profile or avatar image with the following code, didn't get success.

NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:stringPath]];
UIImage *tmpImage = [[UIImage alloc] initWithData:data];
UIImageView *thumbimage;
thumbimage.image = tmpImage;

NSData *imageData1 = UIImageJPEGRepresentation(thumbimage.image,0.5);
NSXMLElement *vCardXML = [NSXMLElement elementWithName:@"vCard" xmlns:@"vcard-temp"];
NSXMLElement *photoXML = [NSXMLElement elementWithName:@"PHOTO"];
NSXMLElement *typeXML = [NSXMLElement elementWithName:@"TYPE" stringValue:@"image/jpeg"];
NSXMLElement *binvalXML = [NSXMLElement elementWithName:@"BINVAL" stringValue:[[NSString alloc] initWithData:imageData1 encoding:NSUTF8StringEncoding]];

[photoXML addChild:typeXML];
[photoXML addChild:binvalXML];
[vCardXML addChild:photoXML];

XMPPvCardTemp *myvCardTemp = [[[self appDelegate] xmppvCardTempModule] myvCardTemp];

if (myvCardTemp) {
    [myvCardTemp setPhoto:imageData1];
    [[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp:myvCardTemp];
}

Please help me to implement the upload image concept to XMPP or correct me If I am doing something wrong in the code.

Thanks in advance.

回答1:

Try converting your image to a Base64 string value for BINVAL instead of using UTF-8 encoding.

See: Convert Image to Base64 string in iOS


XML Syntax

According to the documentation, it is a requirement to use Base64:

The <PHOTO/> element SHOULD contain a <BINVAL/> child whose XML character data is Base64-encoded data for the avatar image.

Image Restriction

The image data MUST conform to the base64Binary datatype [7] and thus be encoded in accordance with Section 6.8 of RFC 2045 [8], which recommends that base64 data should have lines limited to at most 76 characters in length. However, any whitespace characters (e.g., '\r' and '\n') MUST be ignored.

See also: XEP-0153: vCard-Based Avatars XML Syntax



回答2:

Hello I succeeded to have my avatar uploaded using your code but with some changes:

UIImage *tmpImage = [UIImage imageNamed: @"myimage.jpg"];

NSData *imageData1 = UIImageJPEGRepresentation(tmpImage,0.0);

NSXMLElement *vCardXML = [NSXMLElement elementWithName:@"vCard" xmlns:@"vcard-temp"];
NSXMLElement *photoXML = [NSXMLElement elementWithName:@"PHOTO"];
NSXMLElement *typeXML = [NSXMLElement elementWithName:@"TYPE" stringValue:@"image/jpg"];

NSString *image64 = [self encodeToBase64String:tmpImage];

NSXMLElement *binvalXML = [NSXMLElement elementWithName:@"BINVAL" stringValue:image64];

[photoXML addChild:typeXML];
[photoXML addChild:binvalXML];
[vCardXML addChild:photoXML];


XMPPvCardTemp *myvCardTemp = [[[self appDelegate] xmppvCardTempModule] myvCardTemp];

if (myvCardTemp) {
    [myvCardTemp setPhoto:imageData1];
    [[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp:myvCardTemp];
}

This class converts to base64 as Keith suggested

- (NSString *)encodeToBase64String:(UIImage *)image {
    return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}

futhermore, I modified XMPPvCardTemp.h to expose this method:

- (void)setPhoto:(NSData *)data;

Anyway, the XEP-0054 extension header

#import "XMPPvCardTemp.h"

is requested.

Maybe this can be helpful for someone.



回答3:

Hi I used a different way but it works very good. I made an interface where the user can select an image from gallery, I used ImagePicker to do this, then change the name of the image from the user JID, then u must upload the image to server... I used FTP but u can use a different way like HTTPS or something like that... At this point you have the image in server with the user's JID... now add SDWebImage to your project

 NSString *photourl=@"http://your image host/";
    //adding 2 strings for example http://your image host/guy1@myserver.com
    NSString *fullUrl = [photourl stringByAppendingString:fjid];
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 54, 54)];
    [imageView setImageWithURL:[NSURL URLWithString:fullUrl]


    placeholderImage:[UIImage imageNamed:@"use an image while the image is loaded"]];
    [self.view addSubview:imageView];
    imageView.layer.cornerRadius = 25.0;
    imageView.layer.masksToBounds = YES;
    imageView.frame = CGRectMake(152, 2, 54, 54); //set the proper frame here
    [self.titleButton addSubview:imageView];

hope this help you