这一个会杀了我。除了这个愚蠢的问题之外,我很接近完成这个任务。我不确定我能够充分描述这个问题,但我会尝试。iOS:将.jpg图像作为base64发送给tcp服务器
我的企业应用程序使用iPhone相机为我们的现场工作人员购买的收据拍照。我使用了一个非常酷的API将jpeg数据转换为64位(https://github.com/nicklockwood/Base64),通过TCP连接发送到VB 2010服务器,该服务器将其读取为文本字符串并将其转换回二进制文件。
在创建中的Base64文件,它首先保存到磁盘在手机上,因为可能会有更多的图像。然后准备发送时,该进程将读取每个base64文件并一次发送一个。
通过的base64函数创建的文本字符串是相当大的,起初它只是发送约131,000字节,这将转换回二进制轻松不够好,但会使大约1/4到1/3的图像。我刚才发现数据被截断,因为应用程序试图超越自己。
于是我找到了一个很好的片段,教我如何使用NSStreamEventHasSpaceAvailable事件中的Base64字符串分割成若干块,按顺序发送。 (http://www.ios-developer.net/iphone-ipad-programmer/development/tcpip/tcp-client)在发送完整文件时效果很好 - 也就是说,服务器接收到的结果文件的大小正确,与发送之前的base64文件相同。
这里的问题是,在某些时候由服务器接收到的文件已损坏,因为它似乎在文件的开头一切重新开始......换句话说,数据开始重演。
奇怪的是,重复部分每次都会在接收文件中的相同位置开始:位置131016.它不会在文件末尾开始重复,它只会在该位置中断文件点并跳回到开头。碰巧那是在我开始使用HasSpaceAvailable事件之前发送的文件的大小。我无法弄清楚价值131,016的重要性。某处的最大缓冲区大小?
使用各种NSLogs和断点的,我非常确定数据在离开电话这种方式,而不是由服务器加密。我还在一个NSMailComposeViewer方法中写道,它会将base64文件作为附件通过电子邮件发送给我,并且它完美地通过了。
下面是当从磁盘中读取该文件并发送到服务器的代码:
int i;
for (i = 0; i < [imageList count];i++){
NSArray *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory= [documentsPath objectAtIndex:0]; //Get the docs directory
NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:imageFileName];
imageFileName = [imageList objectAtIndex:i] ;
NSLog(@"Image index: %d - image file name: %@",i,imageFileName);
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:imagePath];
if(fileExists == YES){
NSString *imageReceipt = [NSString stringWithContentsOfFile:imagePath encoding:NSASCIIStringEncoding error:nil];
int32_t imageStringLen = [imageReceipt length];
NSString *imageSize = [NSString stringWithFormat: @"%d",imageStringLen];
NSString *currentImage = [NSString stringWithFormat:@"image,%@,%@,%@",imageFileName,imageSize,imageReceipt]; //creates a CSV string with a header string with the filename and file size, and then appends the image data as the final comma-separated string.
data = [[NSMutableData alloc] initWithData:[currentImage dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
然后在这里是使用HasSpaceAvailable事件的代码:
case NSStreamEventHasSpaceAvailable:
if (data != nil)
{
//Send rest of the packet
int ActualOutputBytes = [outputStream write:[data bytes] maxLength:[data length]];
int totalLength = [data length];
if (ActualOutputBytes >= totalLength)
{
//It was all sent
data = nil;
}
else
{
//Only partially sent
[data replaceBytesInRange:NSMakeRange(0, ActualOutputBytes) withBytes:NULL length:0]; //Remove sent bytes from the start
}
}
break;
(我特别是这样的代码,因为它允许放置一个ProgressView控制在屏幕上。)
网络流事件处理程序代码是在根视图控制器,但图像base64中的数据正从另一个视图控制器发送。我的直觉告诉我,这不是一个问题,因为它直到现在都运行良好,但是使用更短的字符串。
现在,还有一个可能相关的问题 - 可能是。除非我关闭应用程序,否则我似乎无法完成数据的传输。我猜,服务器在连接关闭之前不会看到它。我曾尝试将[outputStream close]放置在代码中的各个位置,但无济于事。我也尝试用换行或回车或两者都终止base64字符串。
服务器被编程为当文件看到正确的字节数时保存该文件,但在应用程序关闭之前永远不会发生。我知道通过在服务器上使用WireShark正在接收一些数据,但正如我所说的,剩下的数据直到应用程序关闭时才会到达。我怀疑这最后一部分(完成传输)是问题,但对于我的生活,我找不到任何网上解决这个问题的东西,除非我太无知,不知道要使用哪些搜索条件....很有可能。
我希望我已经提供了足够的信息。谁能帮我?
当计算边界的大小(131016)时,我忽略了考虑头字节。头文件将56个字节添加到文件中,使整个传输(截断之前)为131072,即2^17。我仍然不知道它的意义。这是我的理解,NSData可以容纳多达2GB。 – 2013-02-18 19:51:06