How to send image data in NSOutputStream with large data

2k views Asked by At

I have a picker to pick image and i try the image which have < 131768 bytes. So when i try the image with large bytes (ex: 300000 bytes) the OutputStream cant write data to stream. What is the correct way to write large data in output stream. Thank in advanced.Here is my code

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [self openStream];
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    NSData *imgData = UIImageJPEGRepresentation(image,0.4f);
    NSInteger writeResult = 0;

    // imgData.leng = 300000k

    // Image data only send <131768 bytes

    NSMutableData *completeData = [[NSMutableData alloc]init];
    [completeData appendData:imgData];

    NSInteger bytesWritten = 0;
    while ( completeData.length > bytesWritten )
    {


            writeResult += [self.outputStream write:[completeData bytes]+bytesWritten maxLength:[completeData length]-bytesWritten];

        //sending NSData over to server

        NSLog(@"WRITE RESULT : %ld",(long)writeResult);
        if ( writeResult == -1 )
            NSLog(@"error code here");

        else
            bytesWritten += writeResult;

        if (bytesWritten == writeResult) {
        // Dismiss view when byteswritten == writeresult
            [self dismissViewControllerAnimated:YES completion:nil];
        }
    }

}

and ReceiveServer code

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our
// network stream.
{

    switch (eventCode) {
        case NSStreamEventOpenCompleted: {

            NSLog(@"NSStreamEventOpenCompleted");
        } break;
        case NSStreamEventHasBytesAvailable: {

            uint8_t         buffer[1035];
            // Pull some data off the network.
            NSInteger       bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
            // Get data from client
            self.dataa = [NSData dataWithBytes:buffer length:bytesRead];


            /* Sub data string to define image/video/string
             ffd8ff is JPEG data
             62706c is String Data */

            NSString *dataString = [NSString stringWithFormat:@"%@",self.dataa];
            NSString *subDataString = [dataString substringWithRange:NSMakeRange(1, 6)];


            // If data string equal define Image string
            if ([subDataString isEqualToString:kDefineImageString]) {
                self.isImage = YES;

                // check input stream
                if (aStream == self.networkStream) {

                    // append the data at the top to define type
                    [sharedManager.pictureMutableData appendData:self.dataa];
                    int len;
                    // while Input stream available to read
                    while ([self.networkStream hasBytesAvailable]) {
                        // read buffer with length
                        len = [self.networkStream read:buffer maxLength:sizeof(buffer)];

                        // if length of buffer > 0 append data to sharedManager.pictureMutableData (a mutable data to store all data of UIImage )
                        if (len > 0) {
                            NSData *pictureData = [NSData dataWithBytes:buffer length:len];
                            [sharedManager.pictureMutableData appendData:pictureData];

                        }

                    }

                }
  }
            // When done save image if data is UIImage , if string data do nothing
        case NSStreamEventHasSpaceAvailable: {
            if (self.isImage == YES) {
                //send image data

                [self _didReceiveDataImage:sharedManager.pictureMutableData];
                self.isImage == NO;

            }
            else if (self.isString == NO)
            {
                // Do nothing
            }
        } break;
        case NSStreamEventErrorOccurred: {
            [self _stopReceiveWithStatus:@"Stream open error"];
        } break;

            // Close stream when end
        case NSStreamEventEndEncountered:
        {
            [aStream close];
            [aStream removeFromRunLoop:[NSRunLoop currentRunLoop]
                               forMode:NSDefaultRunLoopMode];

            aStream = nil; // stream is ivar, so reinit it
            break;
            //            NSMutableData *dataImageMut = [NSMutableData dataWithData:dataImage];
            //            [self _didReceiveDataImage:dataImageMut];

        }   break;
        default: {
        } break;
    }
1

There are 1 answers

0
Rob On BEST ANSWER

Your write routine has a number of issues:

  1. Where you have

    writeResult += [self.outputStream write:[completeData bytes]+bytesWritten maxLength:[completeData length]-bytesWritten];
    

    You, instead want:

    writeResult = [self.outputStream write:[completeData bytes]+bytesWritten maxLength:[completeData length]-bytesWritten];
    
  2. If writeResult is -1, you want to immediately return.

  3. Right now you're dismissing the picker if bytesWritten is equal to writeResult. That doesn't really make sense. I would take this dismissing of the picker out of the for loop altogether and make sure you dismiss it regardless.


As an aside, rather than getting a low resolution JPEG representation, I'd personally suggest retrieving the data for the asset directly. See https://stackoverflow.com/a/25322412/1271826.

This ensures that you have no loss of quality and/or change of file size. It is also far more efficient use of memory.