I am trying to send a small image along with some XML information to App Engine from my iPhone app. I am having trouble with the image somewhere along the path. There is no error given and data is being transfered into a Blob entry in Datastore Viewer but the blob files on App Engine do not appear in Blob Viewer. I have a suspicion that the image is being messed up in one of my transforms in App Engine, or is not being stored as the correct type in App Engine. What do you think?
On the iPhone, here is the relevant section that encodes the image (using a standard base64Encoding function) and adds it to a GDataXMLElement, which then gets added to a GDataXMLDoc and sent with ASIHTTPRequest:
NSString *dataString = [self.data base64Encoding];
GDataXMLElement *tempXMLElement = [GDataXMLElement elementWithName:#"data" stringValue: dataString];
[imageElement addChild: tempXMLElement];
the ASIHTTPRequest part:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL: url];
[request setDelegate: self];
[request addRequestHeader:#"User-Agent" value: [NSString stringWithFormat:#"MyApp:%#", version]];
[request addRequestHeader:#"Content-Type" value:#"text/xml"];
[request setShouldStreamPostDataFromDisk:YES];
[request appendPostDataFromFile: path];
[request start];
On App Engine in Python (most likely where a problem lies):
image_data_xml_element = image_xml_node.getElementsByTagName("data")[0]
image_data_base64_unicode = image_data_xml_element.firstChild.data
image_data_base64_ascii = image_data_unicode.encode("utf8")
image_data_string = binascii.a2b_base64(image_data_base64_ascii)
new_image.data = db.Blob(image_data_string)
Additionally I have tried:
image_data_xml_element = image_xml_node.getElementsByTagName("data")[0]
image_data_base64_unicode = image_data_xml_element.firstChild.data
image_data_string = base64.b64decode(image_data_base64_unicode)
new_image.data = db.Blob(image_data_string)
Edit: For completeness, here is the objective-c base64 library I am using - it doesn't look like what I expected:
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- (NSString *)base64Encoding;{
if ([self length] == 0)
return #"";
char *characters = malloc((([self length] + 2) / 3) * 4);
if (characters == NULL)
return nil;
NSUInteger length = 0;
NSUInteger i = 0;
while (i < [self length]){
char buffer[3] = {0,0,0};
short bufferLength = 0;
while (bufferLength < 3 && i < [self length])
buffer[bufferLength++] = ((char *)[self bytes])[i++];
// Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
if (bufferLength > 1)
characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
else characters[length++] = '=';
if (bufferLength > 2)
characters[length++] = encodingTable[buffer[2] & 0x3F];
else characters[length++] = '=';
}
return [[[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES] autorelease];
}
The Blob Viewer displays files uploaded with the Blobstore API, not those added to regular datastore entities in Blob Properties.
What I ended up doing was sending the image to the Blobstore prior to sending the XML then, if successful, send the XML including a key to the blobstore image data. I did not realize initially that Blobstore was a different entity than Blobs stored in the Datastore.
Thanks
Related
i am working on in app purchase app in which i want to verify purchase transaction receipt with my developer server along with other information like Device VendorID, software version , device name and product id wish to buy.
I am using NSDictionary to create Json but it crash when i try to add
NSMutableArray *MainOBJ = [NSMutableArray arrayWithObjects:IDdict,deviceData,kMyFeatureIdentifier,jsonObjectString,nil];
in which IDdict is device id string , deviceData is dictionary which content device information like name , software version and kMyFeatureIdentifier is product id NSstring wish to buy. and jsonObjectString is encoded transaction receipt string.
here is my code
- (void)verifyReceipt:(SKPaymentTransaction *)transaction {
//TODO
// currently working on JSON to send to server .
NSLog(#"In verifyReceipt method");
jsonObjectString = [self encode:(uint8_t*)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length];
// jsonObjectString=#"TESTING";
NSLog(#"Json Object encoded receipt is %#",jsonObjectString);
NSString *IDdict = [[NSString alloc ]initWithString:[UIDevice currentDevice].identifierForVendor.UUIDString]; // Device UDID
NSArray *objects = [NSArray arrayWithObjects:#"NULL",[[UIDevice currentDevice] model],[[UIDevice currentDevice] name],nil];
NSArray *keys = [NSArray arrayWithObjects:#"serial",#"constructor",#"name",nil];
NSDictionary *deviceData = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; // Device information like name , device model , serial number
NSLog(#"Json question dict created");
//TODO: **It crash here**
NSMutableArray *MainOBJ = [NSMutableArray arrayWithObjects:IDdict,deviceData,kMyFeatureIdentifier,jsonObjectString,nil]; // purchased Item ID of previous item
NSMutableArray *MainKeys = [NSMutableArray arrayWithObjects:#"ID",#"device",#"video","#receiptData", nil];
NSMutableDictionary *MainDict = [NSMutableDictionary dictionaryWithObjects:MainOBJ forKeys:MainKeys]; // final string of data
NSLog(#"Json Main dict created");
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:MainDict options:NSJSONWritingPrettyPrinted error:&error];
NSString *resultAsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"Purchase product Json string:\n%#", resultAsString);
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[[NSURL alloc] initWithString:#"http://xyz/dev.php/video/verifyReceipt"]];
[request setPostValue:resultAsString forKey:#"verify"];
[request setDidFinishSelector:#selector(requestDone:)];
[request setTimeOutSeconds:120];
[request setDelegate:self];
[request setNumberOfTimesToRetryOnTimeout:2];
[request setDownloadProgressDelegate:self];
request.showAccurateProgress = YES;
i got "NSLog(#"Json question dict created");" in my log after it crashes.
and my expected json format is like this
{
"ID" : "E6E95901-006B-4569-8D2B-FA29A0307F80",
"device" : {
"name" : "iPad Simulator",
"constructor" : "iPad Simulator",
"serial" : "NULL"
},
"video" : "com.amm.happyclip.4445Video",
"receiptData":"DSKLFKSGERPOKFLJGMZEKLEMSERLKEMZTRKGDGFLefklezkgem"
}
Screenshot of error
Any suggestion , help appreciated Thank you
Encoding method which return string and i just assign that string to "jsonObjectString"
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *output = (uint8_t *)data.mutableBytes;
for (NSInteger i = 0; i < length; i += 3) {
NSInteger value = 0;
for (NSInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger index = (i / 3) * 4;
output[index + 0] = table[(value >> 18) & 0x3F];
output[index + 1] = table[(value >> 12) & 0x3F];
output[index + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[index + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
Maybe each object in MainOBJ is nil and if you create dictionary with nil object it crashes your app, or they are already released.
try to log objects from MainOBJ array.
I am working on iOS native app for getting attachments from salesforce.
I have to show the salesforce attachments in my iPhone app for particular object like Leads,Contacts etc. For that i am using Rest Api and got response body. But in response body there is url but i want binary data of attachment body.
Here is my code:
My rest api request
NSString *attachments=[NSString stringWithFormat:#"select Name,Body, ContentType from Attachment"];
SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:attachments];
[[SFRestAPI sharedInstance] send:request delegate:self];
I get response in body in following format:
{
Body = "/services/data/v23.0/sobjects/Attachment/00P90000004SRFlEAO/Body";
ContentType = "application/video";
Name = "Video.MOV";
attributes = {
type = Attachment;
url = "/services/data/v23.0/sobjects/Attachment/00P90000004SRFlEAO";
};
}
Using this code to download after get body url:
SFRestRequest* downloadRequest = [self requestForFileContents:#"/services/data/v23.0/sobjects/Attachment/00P90000004SRFlEAO/Body"];
- (SFRestRequest *) requestForFileContents:(NSString *) path {
NSMutableDictionary *params = [NSMutableDictionary dictionary];
SFRestRequest *request = [SFRestRequest requestWithMethod:SFRestMethodGET path:path queryParams:params];
request.parseResponse = NO;
return request;}
You have to make a GET request to the URL returned in the Body field to fetch the actual binary content.
Check this code:
id url = #"http://blogs.independent.co.uk/wp-content/uploads/2012/12/google-zip.jpg";
[self getImageBase64:url];
-( NSString *) AFBase64EncodedStringFromString: (NSData*) data
{
NSUInteger length = [data length];
NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t *input = (uint8_t *)[data bytes];
uint8_t *output = (uint8_t *)[mutableData mutableBytes];
for (NSUInteger i = 0; i < length; i += 3) {
NSUInteger value = 0;
for (NSUInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
NSUInteger idx = (i / 3) * 4;
output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
}
-(NSString *) getImageBase64:(NSString *) url
{
NSURLRequest * imageUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLResponse * response=nil;
NSError * error =nil;
NSData * data = [NSURLConnection sendSynchronousRequest:imageUrlRequest returningResponse:&response error:&error];
if(error == nil)
{
return [self AFBase64EncodedStringFromString:data];
}
return nil;
}
I want to send an image to a web server running .Net which is not Restful .
I have tried a lot of things to convert the image into string and then sending it.Like using initWithData:encoding: and also tried it with converting the image data into base64encodedstring by the method given in this question
iPhone to MS SQL Image Data Type Conversion Question
But no luck.
Then I thought of looking on facebook api for uploading images on facebook wall.Using this tutorial the image can be uploaded to facebook
http://www.raywenderlich.com/1626/how-to-post-to-a-users-wall-upload-photos-and-add-a-like-button-from-your-iphone-app
But the problem is, it is using asihttprequest to send the data on the facebook wall and I cannot see the raw data in the request will uploading the image . Can anyone help me out.
I tried it at my end. First I converted to base64encoding like this:
NSString *str64;
if(Image){
NSData *imageData = UIImageJPEGRepresentation(Image,0.75);
str64 = [imageData base64Encoding];
}
Then I added into a dictionary and then added that dictionary into an array so that I can pass it as a JSON string in request's body.
NSMutableArray *ParaArray =[[NSMutableArray alloc]init];
NSDictionary *ParaDictionary=[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:#"%#",Userid], #"userid",
[NSString stringWithFormat:#"%#",[Imagename URLEncodedString]], #"imagename",
[NSString stringWithFormat:#"%#",DateNTime], #"datetime",
[NSString stringWithFormat:#"%#",ImageLocation], #"imagelocation",
str64,#"image",
nil]; // set the parameter
[ParaArray addObject:ParaDictionary];
There after using ASIFormDataRequest I sent the image to server using this snippet:
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setPostValue:[ParaArray JSONRepresentation] forKey:#"bulk_data"];
//[ParaDictionary release];
[ParaArray release];
[request setTimeOutSeconds:20];
[request startSynchronous];
It worked fine for me. I hope it helps you as well.
Data is passed in form of a string and we can directly use the base64Encoding methods by copy pasting them. Though you might know them still here they are:
- (NSString *) base64Encoding {
return [self base64EncodingWithLineLength:0];
}
- (NSString *) base64EncodingWithLineLength:(NSUInteger) lineLength {
const unsigned char *bytes = [self bytes];
NSMutableString *result = [NSMutableString stringWithCapacity:[self length]];
unsigned long ixtext = 0;
unsigned long lentext = [self length];
long ctremaining = 0;
unsigned char inbuf[3], outbuf[4];
unsigned short i = 0;
unsigned short charsonline = 0, ctcopy = 0;
unsigned long ix = 0;
while( YES ) {
ctremaining = lentext - ixtext;
if( ctremaining <= 0 ) break;
for( i = 0; i < 3; i++ ) {
ix = ixtext + i;
if( ix < lentext ) inbuf[i] = bytes[ix];
else inbuf [i] = 0;
}
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
outbuf [3] = inbuf [2] & 0x3F;
ctcopy = 4;
switch( ctremaining ) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for( i = 0; i < ctcopy; i++ )
[result appendFormat:#"%c", encodingTable[outbuf[i]]];
for( i = ctcopy; i < 4; i++ )
[result appendString:#"="];
ixtext += 3;
charsonline += 4;
if( lineLength > 0 ) {
if( charsonline >= lineLength ) {
charsonline = 0;
[result appendString:#"\n"];
}
}
}
return [NSString stringWithString:result];
}
I'm consuming a web service in my iPhone app. The web service method returns a response which has several fields (eg. ID, Description, etc..). One of these fields contains binary image data which I need to convert to UIImage in my iPhone application.
I'm using a NSXMLParser successfully to extract data from the XML response. In the parser:foundCharacters: selector of the XMLParser, it gives a NSString* pointing to the string within each field. Since this is a string, this is what I do to read image data when i encounter the image field:
UIImage *img = [[UIImage alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]];
But img variable is still "nil" after this line. Seems like the data from XML string is not compatible with conversion. What am I doing wrong here? (I'm capable of reading other fields into my variables but not this image data field)
Thanks in advance..
Following fbrereto's answer, I managed to convert the string into NSData using a code sample at this link: http://www.cocoadev.com/index.pl?BaseSixtyFour (scroll to the code sample by MiloBird user). Now I can construct the image successfully.
It uses objective-c categories to add the selector + (id)dataWithBase64EncodedString:(NSString *)string; to the NSData class. Here's the necessary code sample I extracted from the above link:
//MBBase64.h
#interface NSData (MBBase64)
+ (id)dataWithBase64EncodedString:(NSString *)string; // Padding '=' characters are optional. Whitespace is ignored.
#end
//MBBase64.m
static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#implementation NSData (MBBase64)
+ (id)dataWithBase64EncodedString:(NSString *)string;
{
if (string == nil)
[NSException raise:NSInvalidArgumentException format:nil];
if ([string length] == 0)
return [NSData data];
static char *decodingTable = NULL;
if (decodingTable == NULL)
{
decodingTable = malloc(256);
if (decodingTable == NULL)
return nil;
memset(decodingTable, CHAR_MAX, 256);
NSUInteger i;
for (i = 0; i < 64; i++)
decodingTable[(short)encodingTable[i]] = i;
}
const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
if (characters == NULL) // Not an ASCII string!
return nil;
char *bytes = malloc((([string length] + 3) / 4) * 3);
if (bytes == NULL)
return nil;
NSUInteger length = 0;
NSUInteger i = 0;
while (YES)
{
char buffer[4];
short bufferLength;
for (bufferLength = 0; bufferLength < 4; i++)
{
if (characters[i] == '\0')
break;
if (isspace(characters[i]) || characters[i] == '=')
continue;
buffer[bufferLength] = decodingTable[(short)characters[i]];
if (buffer[bufferLength++] == CHAR_MAX) // Illegal character!
{
free(bytes);
return nil;
}
}
if (bufferLength == 0)
break;
if (bufferLength == 1) // At least two characters are needed to produce one byte!
{
free(bytes);
return nil;
}
// Decode the characters in the buffer to bytes.
bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
if (bufferLength > 2)
bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
if (bufferLength > 3)
bytes[length++] = (buffer[2] << 6) | buffer[3];
}
realloc(bytes, length);
return [NSData dataWithBytesNoCopy:bytes length:length];
}
#end
Thank you all!
The trick with NSString is that there is an implicit encoding associated with the data it contains. The image you are receiving, however, is likely in a format that will not convert properly, as it is either binary data or some lossless encoding of binary data (e.g., base64). The trick, then, is to make sure you don't let NSString perform any encoding conversions at all, otherwise your image data will be corrupted. Instead of using dataUsingEncoding: I would try an API more like getBytes:maxLength:usedLength:encoding:options:range:remainingRange. While more complex than dataUsingEncoding: I think it'll give you the flexibility you need to get just the data from the NSString and nothing more.
How to convert NSData to base64. I have NSData and want to convert into base64 how can I do this?
EDIT
As of OS X 10.9 / iOS 7, this is built into the frameworks.
See -[NSData base64EncodedDataWithOptions:]
Prior to iOS7/OS X 10.9:
Matt Gallagher wrote an article on this very topic. At the bottom he gives a link to his embeddable code for iPhone.
On the mac you can use the OpenSSL library, on the iPhone he writes his own impl.
//from: http://cocoadev.com/BaseSixtyFour
+ (NSString*)base64forData:(NSData*)theData {
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4;
output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
}
As an update, the iOS7 SDK has a category on NSData (NSDataBase64Encoding) with methods
-[NSData base64EncodedStringWithOptions:]
-[NSData initWithBase64EncodedString:options:]
-[NSData initWithBase64EncodedData:options:]
-[NSData base64EncodedDataWithOptions:]
Should avoid having to roll your own category method
Super easy drop-in Google library code here.
Just use +rfc4648Base64StringEncoding to get an instance, then use the encode/decode functions.
It's a beautiful thing. (Don't forget to grab the header file and the GTMDefines.h header from the root, though.)
Its not easy. As in there's no built in support for this in c or obj-c. Here's what Im doing (Which is basically having the CL do it for me):
- (NSString *)_base64Encoding:(NSString *) str
{
NSTask *task = [[[NSTask alloc] init] autorelease];
NSPipe *inPipe = [NSPipe pipe], *outPipe = [NSPipe pipe];
NSFileHandle *inHandle = [inPipe fileHandleForWriting], *outHandle = [outPipe fileHandleForReading];
NSData *outData = nil;
[task setLaunchPath:#"/usr/bin/openssl"];
[task setArguments:[NSArray arrayWithObjects:#"base64", #"-e", nil]];
[task setStandardInput:inPipe];
[task setStandardOutput:outPipe];
[task setStandardError:outPipe];
[task launch];
[inHandle writeData:[str dataUsingEncoding: NSASCIIStringEncoding]];
[inHandle closeFile];
[task waitUntilExit];
outData = [outHandle readDataToEndOfFile];
if (outData)
{
NSString *base64 = [[[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding] autorelease];
if (base64)
return base64;
}
return nil;
}
And you use it like this:
NSString *b64str = [strToConvert _base64Encoding:strToConvert];
And this isn't my code - I found it here: http://www.cocoadev.com/index.pl?BaseSixtyFour and it works great. You could always turn this into a +() method.
Oh, and to get your NSData to an NSString for this method:
NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
iOS has always included built in support for base64 encoding and decoding. If you look at resolv.h you should see the two functions b64_ntop and b64_pton . The Square SocketRocket library provides a reasonable example of how to use these functions from objective-c.
These functions are pretty well tested and reliable - unlike many of the implementations you may find in random internet postings.
Don't forget to link against libresolv.dylib.
If you link against the iOS 7 SDK, you can use the newer methods initWithBase64Encoding: and base64EncodedDataWithOptions:. These exist in previous releases, but were private. So if you link against the 6 SDK, you may run into undefined behavior. This would be an example of how to use this only when linking against the 7 SDK:
#ifndef __IPHONE_7_0
// oh no! you are using something unsupported!
// Call and implementation that uses b64_pton here
#else
data = [[NSData alloc] initWithBase64Encoding:string];
#endif
I modified the code above to meet my needs, building an HTTP POST. I was able to skip the NSString step, and include line breaks in the BASE64 code, which at least one web server found more palatable:
#define LINE_SIZE 76
//originally from: http://www.cocoadev.com/index.pl?BaseSixtyFour
// via joshrl on stockoverflow
- (void) appendBase64Of: (NSData *)inData to:(NSMutableData *)outData {
const uint8_t* input = (const uint8_t*)[inData bytes];
NSInteger length = [inData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
uint8_t buf[LINE_SIZE + 4 + 2];
size_t n = 0;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
buf[n + 0] = table[(value >> 18) & 0x3F];
buf[n + 1] = table[(value >> 12) & 0x3F];
buf[n + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
buf[n + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
n += 4;
if (n + 2 >= LINE_SIZE) {
buf[n++] = '\r';
buf[n++] = '\n';
[outData appendBytes:buf length:n];
n = 0;
}
}
if (n > 0) {
buf[n++] = '\r';
buf[n++] = '\n';
[outData appendBytes:buf length:n];
}
return;
}