gpt4 book ai didi

iphone - 从 iPhone 上传文件时出现 POSIX 错误 12 ("Cannot allocate memory"

转载 作者:技术小花猫 更新时间:2023-10-29 11:24:54 26 4
gpt4 key购买 nike

我正在开发一个 iPhone 应用程序,该应用程序涉及将相机中的完整照片(每张通常在 1.5 到 2.0 MB 之间)及其缩略图(小得多)上传到 Amazon S3。

缩略图总是会成功上传,但有时完整的图像不会,当它们失败时,它们会失败并显示 POSIX 错误代码 12,又名 ENOMEM。但是,我添加了调试代码以在发生错误时打印可用内存量,并且总是有相当多的可用内存,通常超过 100 MB。

此外,当通过 3G 进行上传时,错误会更频繁地出现,而通过 wifi 时则更少——这看起来很奇怪,因为请求没有下载太多,并且正在上传的文件已经在内存中(我'我也尝试过从磁盘流式传输它,但没有任何改进)。

我已经尝试使用 NSURLConnection、Foundation CFHTTP* 函数和 ASIHTTPRequest 库上传文件,但无论如何,错误发生的频率相同。更奇怪的是,我的所有谷歌搜索都揭示了最终用户有时会从 Safari 获得错误代码 12——我还没有看到任何 iOS 开发人员提到它。我正在使用继承的代码库,所以它可能有问题,但我什至不确定要查找什么。任何见解将不胜感激!

最佳答案

我能够解决此问题的唯一方法是直接使用套接字并手动形成 HTTP header 。所以我的上传代码目前看起来像这样:

- (void)socketClose
{
[_inputStream setDelegate:nil];
[_inputStream close];
[_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
SCR_RELEASE_SAFELY(_inputStream);

[_outputStream setDelegate:nil];
[_outputStream close];
[_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
SCR_RELEASE_SAFELY(_outputStream);

SCR_RELEASE_SAFELY(_headerBuffer);
}

- (void)sendRequest
{
[self socketClose];
SCR_RELEASE_SAFELY(_headerBuffer);

if (!_shouldCancel)
{
NSString *httpMessage = [NSString stringWithFormat:@"POST upload.php HTTP/1.1\r\n"
"Host:"
#ifndef TESTBED
" %@"
#endif
"\r\n"
"User-Agent: MyApp/3.0.0 CFNetwork/534 Darwin/10.7.0\r\n"
"Content-Length: %d\r\n"
"Accept: */*\r\n"
"Accept-Language: en-us\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Connection: keep-alive\r\n\r\n"
"data="
#ifndef TESTBED
, [self.serverUrl host]
#endif
, _bytesToUpload];

NSString *key = @"data=";
NSData *keyData = [key dataUsingEncoding:NSASCIIStringEncoding];
_bytesToUpload -= [keyData length];
_bytesToUpload = MAX(0, _bytesToUpload);

_headerBuffer = [[NSMutableData alloc] initWithData:[httpMessage dataUsingEncoding:NSUTF8StringEncoding]];

_writtenDataBytes = 0;

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault
, (CFStringRef)[self.serverUrl host]
#ifdef TESTBED
, 8888
#else
, 80
#endif
, (CFReadStreamRef *)(&_inputStream)
, (CFWriteStreamRef *)(&_outputStream));

[_inputStream setDelegate:self];
[_outputStream setDelegate:self];

[_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

[_inputStream open];
[_outputStream open];
}
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
if (_outputStream == theStream)
{
switch (streamEvent)
{
case NSStreamEventOpenCompleted:
{
[self regenerateTimeoutTimer];
break;
}
case NSStreamEventHasSpaceAvailable:
{
SCR_RELEASE_TIMER(_timeoutTimer);
NSInteger length = _headerBuffer.length;

if (length > 0)
{
NSInteger written = [_outputStream write:(const uint8_t *)[_headerBuffer bytes] maxLength:length];
NSInteger rest = length - written;

if (rest > 0)
{
memmove([_headerBuffer mutableBytes], (const uint8_t *)[_headerBuffer mutableBytes] + written, rest);
}

[_headerBuffer setLength:rest];
}
else
{
const uint8_t *dataBytes = [_data bytes];

while ([_outputStream hasSpaceAvailable] && (_writtenDataBytes < _bytesToUpload))
{
NSInteger written = [_outputStream write:dataBytes
maxLength:MIN(_dataLength, _bytesToUpload - _writtenDataBytes)];

if (written > 0)
{
_writtenDataBytes += written;
}
}
}

[self regenerateTimeoutTimer];

break;
}
case NSStreamEventErrorOccurred:
{
SCR_RELEASE_TIMER(_timeoutTimer);
[self reportError:[theStream streamError]];
break;
}
case NSStreamEventEndEncountered:
{
SCR_RELEASE_TIMER(_timeoutTimer);
[self socketClose];
break;
}
}
}
else if (_inputStream == theStream)
{
switch (streamEvent)
{
case NSStreamEventHasBytesAvailable:
{
SCR_RELEASE_TIMER(_timeoutTimer);

/* Read server response here if you wish */

[self socketClose];

break;
}
case NSStreamEventErrorOccurred:
{
SCR_RELEASE_TIMER(_timeoutTimer);
[self reportError:[theStream streamError]];
break;
}
case NSStreamEventEndEncountered:
{
SCR_RELEASE_TIMER(_timeoutTimer);
[self socketClose];
break;
}
}
}
}

虽然 ASIHTTPRequest 可以在这里工作,但我们决定摆脱这种依赖性,既为了获得性能,又为了让一切都在我们自己的准确控制之下。您可以使用 Wireshark 工具来调试此类内容。

关于iphone - 从 iPhone 上传文件时出现 POSIX 错误 12 ("Cannot allocate memory",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4542459/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com