使用Buffer iOS 7上传

大卫·奥哈拉(DavidOhara)

我正在尝试使用随机数据实现上传并测量速度。现在,我正在生成这样的随机NSData:

void * bytes = malloc("");
NSData * myData = [NSData dataWithBytes:bytes length:"bytes"];
free("bytes");

但是,如果我要上传一个大文件,将会出现内存问题。

我的上传过程是这样的:

NSURLSessionConfiguration *sessionConfig =
[NSURLSessionConfiguration defaultSessionConfiguration];

NSURLSession *session =
[NSURLSession sessionWithConfiguration:sessionConfig
                              delegate:self
                         delegateQueue:nil];

NSURL * urll = [NSURL URLWithString:UPLOAD_SERVER];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:urll];
[urlRequest setHTTPMethod:@"POST"];
[urlRequest addValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];

NSString *boundary = @"*****";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[urlRequest addValue:contentType forHTTPHeaderField: @"Content-Type"];

NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[urlRequest setHTTPBody:body];

void * bytes = malloc(250000000);
NSData * uploadData = [NSData dataWithBytes:bytes length:250000000];
free(bytes);

ulTask = [session uploadTaskWithRequest:urlRequest fromData:uploadData];

[ulTask resume];

有没有办法用缓冲区或其他东西上传?例如生成小数据,将其上传并生成一个新数据,然后再次上传?

我建议只是开始上传并继续发送数据。您还可以通过使用uploadTaskWithStreamedRequest然后创建一个NSInputStream子类来避免创建250mb缓冲区,而该子类将一直提供更多数据,直到您停止它为止。您可以实施URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:监视上传进度(因此可以监视发送数据的速度)。

无论如何,要创建上传请求:

@interface ViewController () <NSURLSessionDelegate, NSURLSessionTaskDelegate>

@property (nonatomic, strong) CustomStream *inputStream;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.inputStream = [[CustomStream alloc] init];

    NSURL *url = [NSURL URLWithString:kURLString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"POST"];

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

    NSURLSessionUploadTask *task = [session uploadTaskWithStreamedRequest:request];

    [task resume];

    // I don't know how you want to finish the upload, but I'm just going 
    // to stop it after 10 seconds

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.inputStream.finished = YES;
    });
}

您显然必须实现适当的委托方法:

#pragma mark - NSURLSessionTaskDelegate

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    NSLog(@"%lld %lld %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
{
    completionHandler(self.inputStream);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"%s: error = %@; data = %@", __PRETTY_FUNCTION__, error, [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding]);
}

#pragma mark - NSURLSessionDataDelegate

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
    self.responseData = [NSMutableData data];
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    [self.responseData appendData:data];
}

CustomStream

static NSInteger const kBufferSize = 32768;

@interface CustomStream : NSInputStream

@property (nonatomic, readonly) NSStreamStatus streamStatus;
@property (nonatomic, getter = isFinished) BOOL finished;

@end

@interface CustomStream ()

@property (nonatomic) NSStreamStatus streamStatus;
@property (nonatomic) void *buffer;

@end

@implementation CustomStream

- (instancetype)init
{
    self = [super init];
    if (self) {
        _buffer = malloc(kBufferSize);
        NSAssert(_buffer, @"Unable to create buffer");
        memset(_buffer, 0, kBufferSize);
    }
    return self;
}

- (void)dealloc
{
    if (_buffer) {
        free(_buffer);
        self.buffer = NULL;
    }
}

- (void)open
{
    self.streamStatus = NSStreamStatusOpen;
}

- (void)close
{
    self.streamStatus = NSStreamStatusClosed;
}

- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len
{
    if ([self isFinished]) {
        if (self.streamStatus == NSStreamStatusOpen) {
            self.streamStatus = NSStreamStatusAtEnd;
        }
        return 0;
    }

    NSUInteger bytesToCopy = MIN(len, kBufferSize);
    memcpy(buffer, _buffer, bytesToCopy);

    return bytesToCopy;
}

- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len
{
    return NO;
}

- (BOOL)hasBytesAvailable
{
    return self.streamStatus == NSStreamStatusOpen;
}

- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
                  forMode:(__unused NSString *)mode
{}

- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
                  forMode:(__unused NSString *)mode
{}

#pragma mark Undocumented CFReadStream Bridged Methods

- (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop
                     forMode:(__unused CFStringRef)aMode
{}

- (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop
                         forMode:(__unused CFStringRef)aMode
{}

- (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags
                 callback:(__unused CFReadStreamClientCallBack)inCallback
                  context:(__unused CFStreamClientContext *)inContext {
    return NO;
}

@end

我建议您参考BJ Homer的文章Subclassing NSInputStream来获得该子类中一些隐秘方法的一些背景知识NSInputStream

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用NSURLSession的iOS FTP上传

来自分类Dev

使用Alamofire从iOS上传PHP

来自分类Dev

使用post -ios上传图像

来自分类Dev

使用iOS 7的Alamofire

来自分类Dev

iOS 7后台上传和POST请求

来自分类Dev

无法使用Application Loader上传iOS应用

来自分类Dev

如何上传可以在具有iOS旧版外观的iOS 7上运行的iOS 6应用

来自分类Dev

如何上传可以在具有iOS旧版Look的iOS 7上运行的iOS 6应用

来自分类Dev

在iOS 7上使用iOS 7之前的外观

来自分类Dev

结合使用Node Buffer或fileStream和formData文件上传

来自分类Dev

使用AFNetworking上传图像iOS时匹配特定的HTML表单

来自分类Dev

使用iOS设备(iPad,iPhone)从网站(HTML表单)上传图像

来自分类Dev

使用AWS iOS SDK 2.0上传的文件的权限

来自分类Dev

iOS使用NSURLSessionUploadTask上传文件但未发送httpbody

来自分类Dev

使用YouTube用户上传的JSON数据填充表格视图-iOS

来自分类Dev

使用AFNetworking上传图像iOS时匹配特定的HTML表单

来自分类Dev

使用YouTube用户上传的JSON数据填充表格视图-iOS

来自分类Dev

iOS使用REST API将图片上传到OneDrive

来自分类Dev

在iOS中使用Socket上传和流式传输视频

来自分类Dev

如何在objective c ios中使用multipart上传图像?

来自分类Dev

在 iOS 中使用 Xcode 上传更新的应用程序版本

来自分类Dev

在iOS 7上无法在iOS 6上使用writeToFile

来自分类Dev

使用iOS 8设备测试iOS 7应用

来自分类Dev

在iOS 7手机上使用iOS 8功能,hidesBarsOnSwipe

来自分类Dev

每次通过管理器上传iOS 7应用时,Xcode错误

来自分类Dev

ios 9-xcode 7-SFSafariViewController-图像上传-相机黑屏

来自分类Dev

每次通过管理器上传iOS 7应用时出现Xcode错误

来自分类Dev

将映像上传到服务器IOS7后,应用程序崩溃

来自分类Dev

在iOS 7中将图像作为多部分文件上传到服务器

Related 相关文章

  1. 1

    使用NSURLSession的iOS FTP上传

  2. 2

    使用Alamofire从iOS上传PHP

  3. 3

    使用post -ios上传图像

  4. 4

    使用iOS 7的Alamofire

  5. 5

    iOS 7后台上传和POST请求

  6. 6

    无法使用Application Loader上传iOS应用

  7. 7

    如何上传可以在具有iOS旧版外观的iOS 7上运行的iOS 6应用

  8. 8

    如何上传可以在具有iOS旧版Look的iOS 7上运行的iOS 6应用

  9. 9

    在iOS 7上使用iOS 7之前的外观

  10. 10

    结合使用Node Buffer或fileStream和formData文件上传

  11. 11

    使用AFNetworking上传图像iOS时匹配特定的HTML表单

  12. 12

    使用iOS设备(iPad,iPhone)从网站(HTML表单)上传图像

  13. 13

    使用AWS iOS SDK 2.0上传的文件的权限

  14. 14

    iOS使用NSURLSessionUploadTask上传文件但未发送httpbody

  15. 15

    使用YouTube用户上传的JSON数据填充表格视图-iOS

  16. 16

    使用AFNetworking上传图像iOS时匹配特定的HTML表单

  17. 17

    使用YouTube用户上传的JSON数据填充表格视图-iOS

  18. 18

    iOS使用REST API将图片上传到OneDrive

  19. 19

    在iOS中使用Socket上传和流式传输视频

  20. 20

    如何在objective c ios中使用multipart上传图像?

  21. 21

    在 iOS 中使用 Xcode 上传更新的应用程序版本

  22. 22

    在iOS 7上无法在iOS 6上使用writeToFile

  23. 23

    使用iOS 8设备测试iOS 7应用

  24. 24

    在iOS 7手机上使用iOS 8功能,hidesBarsOnSwipe

  25. 25

    每次通过管理器上传iOS 7应用时,Xcode错误

  26. 26

    ios 9-xcode 7-SFSafariViewController-图像上传-相机黑屏

  27. 27

    每次通过管理器上传iOS 7应用时出现Xcode错误

  28. 28

    将映像上传到服务器IOS7后,应用程序崩溃

  29. 29

    在iOS 7中将图像作为多部分文件上传到服务器

热门标签

归档