這一個會殺了我。除了這個愚蠢的問題之外,我很接近完成這個任務。我不確定我能夠充分描述這個問題,但我會嘗試。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