zoukankan      html  css  js  c++  java
  • 【iOS】文件上传小记

    iOS由该系统提供API可以实现可以实现文件的上传和下载,有两种方法来。

    NSURLConnectionNSURLSession

    当中NSURLConnection是使用非常久的的一种方式。NSURLSession是新出来的一种方式。


    一、 POST方式上传

    POST方式提交信息默认使用的是 :
    *Content-Type:  application/x-www-form-urlencoded.
    *输入中文时,post方式自己主动进行转义(苹果中自己主动).

    国内的绝大多数站点都採用这样的方式上传文件(支持二进制文件)
    *Content-Type:multipart/form-data(上传文件)
    *都会限制上传文件的大小通常是2M或者更小。


    在苹果中进行上传操作十分麻烦。

    须要拼接好上传所须要的字符串格式。然后才干实现上传。

    (还要加上头部)


    其它平台做的好一点的可能封装好了,不须要自己拼接字符串格式。因此iOS中非常少用这样的方式上传

    演示样例代码:

    #import "XNUploadFile.h"
    
    #define kTimeOut 5.0f
    
    @implementation XNUploadFile
    /** 分隔字符串 */
    static NSString *boundaryStr = @"--";
    /** 本次上传标示字符串 */
    static NSString *randomIDStr;
    /** 上传(php)脚本中,接收文件字段 */
    static NSString *uploadID;
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            /** 本次上传标示字符串 */
            randomIDStr = @"itcastupload";
            /** 上传(php)脚本中。接收文件字段 */
            // 能够咨询公司的站点开发程序猿
            // 或者用FireBug自己跟踪调试
            uploadID = @"uploadFile";
        }
        return self;
    }
    
    #pragma mark - 成员方法.  用NSURLSession来完毕上传
    - (void)uploadFile:(NSString *)path fileName:(NSString *)fileName completion:(void (^)(NSString *string))completion
    {
        // 1. url 提示:真正负责文件上传的是php文件,而不是html文件
        NSURL *url = [NSURL URLWithString:@"http://localhost/new/post/upload.php"];
        
        // 2. request
        NSURLRequest *request = [self requestForUploadURL:url uploadFileName:fileName localFilePath:path];
        
        // 3. session(回话)
        // 全局网络回话,为了方便程序猿使用网络服务
        NSURLSession *session = [NSURLSession sharedSession];
        
        // 4. 数据任务-> 任务都是由回话发起的
        /** URLSession的任务。默认都是在其它线程工作的,默认都是异步的 */
        [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            
            id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
            
            NSLog(@"%@ %@", result, [NSThread currentThread]);
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (completion) {
                    completion(@"下载完毕");
                }
            });
        }] resume];
        
        //    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        //
        //        id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        //
        //        NSLog(@"%@ %@", result, [NSThread currentThread]);
        //
        //        dispatch_async(dispatch_get_main_queue(), ^{
        //            if (completion) {
        //                completion(@"下载完毕");
        //            }
        //        });
        //    }];
        //    
        //    // 5. 启动任务
        //    [task resume];
    }
    
    #pragma mark - 私有方法 : 拼字符串
    /** 拼接顶部字符串 */
    - (NSString *)topStringWithMimeType:(NSString *)mimeType uploadFile:(NSString *)uploadFile
    {
        NSMutableString *strM = [NSMutableString string];
        
        [strM appendFormat:@"%@%@
    ", boundaryStr, randomIDStr];
        [strM appendFormat:@"Content-Disposition: form-data; name="%@"; filename="%@"
    ", uploadID, uploadFile];
        [strM appendFormat:@"Content-Type: %@
    
    ", mimeType];
        
        NSLog(@"顶部字符串:%@", strM);
        return [strM copy];
    }
    
    /** 拼接底部字符串 */
    - (NSString *)bottomString
    {
        NSMutableString *strM = [NSMutableString string];
        
        [strM appendFormat:@"%@%@
    ", boundaryStr, randomIDStr];
        [strM appendString:@"Content-Disposition: form-data; name="submit"
    
    "];
        [strM appendString:@"Submit
    "];
        [strM appendFormat:@"%@%@--
    ", boundaryStr, randomIDStr];
        
        NSLog(@"底部字符串:%@", strM);
        return [strM copy];
    }
    
    /** 指定全路径文件的mimeType */
    - (NSString *)mimeTypeWithFilePath:(NSString *)filePath
    {
        // 1. 推断文件是否存在
        if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
            return nil;
        }
        
        // 2. 使用HTTP HEAD方法获取上传文件信息
        NSURL *url = [NSURL fileURLWithPath:filePath];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        // 3. 调用同步方法获取文件的MimeType
        NSURLResponse *response = nil;
        [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
        
        return response.MIMEType;
    }
    
    /** 上传文件网络请求 */
    - (NSURLRequest *)requestForUploadURL:(NSURL *)url uploadFileName:(NSString *)fileName localFilePath:(NSString *)filePath
    {
        // 0. 获取上传文件的mimeType
        NSString *mimeType = [self mimeTypeWithFilePath:filePath];
        if (!mimeType) return nil;
        
        // 1. 拼接要上传的数据体
        NSMutableData *dataM = [NSMutableData data];
        [dataM appendData:[[self topStringWithMimeType:mimeType uploadFile:fileName] dataUsingEncoding:NSUTF8StringEncoding]];
        // 拼接上传文件本身的二进制数据
        [dataM appendData:[NSData dataWithContentsOfFile:filePath]];
        [dataM appendData:[[self bottomString] dataUsingEncoding:NSUTF8StringEncoding]];
        
        // 2. 设置请求
        NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeOut];
        // 1> 设定HTTP请求方式
        requestM.HTTPMethod = @"POST";
        // 2> 设置数据体
        requestM.HTTPBody = dataM;
        // 3> 指定Content-Type
        NSString *typeStr = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", randomIDStr];
        [requestM setValue:typeStr forHTTPHeaderField:@"Content-Type"];
        // 4> 指定数据长度
        NSString *lengthStr = [NSString stringWithFormat:@"%@", @([dataM length])];
        [requestM setValue:lengthStr forHTTPHeaderField:@"Content-Length"];
        
        return [requestM copy];
    }

    注意:POST上传时,不同意重名.(否则出错)


    二、 PUT方式上传

    session中的upload方法仅仅能用于PUT上传,不能用于POST上传.

    PUT方式上传的优点:(须要身份验证)
    *不用像POST一样,拼一堆字符串.
    *直接base64编码一下身份验证sessionupload一调用即可了.
    *没有文件限制大小.
    *即时通讯里面用的多.(发图片/发语音)

    - (void)putFile
    {
        // 1. url 最后一个是要上传的文件名称
        NSURL *url = [NSURL URLWithString:@"http://localhost/uploads/abcd"]; //abcd为文件名称
        
        // 2. request
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        request.HTTPMethod = @"PUT";
    //    request.HTTPMethod = @"DELETE";
        
        // 设置用户授权
        // BASE64编码:一种对字符串和二进制数据进行编码的一种“最经常使用的网络编码方式”,此编码能够将二进制数据转换成字符串!

    // 是非常多加密算法的底层算法 // BASE64支持反编码,是一种双向的编码方案 NSString *authStr = @"admin:123"; NSString *authBase64 = [NSString stringWithFormat:@"Basic %@", [self base64Encode:authStr]]; [request setValue:authBase64 forHTTPHeaderField:@"Authorization"]; // 3. URLSession NSURLSession *session = [NSURLSession sharedSession]; // 4. 由session发起任务 NSURL *localURL = [[NSBundle mainBundle] URLForResource:@"001.png" withExtension:nil]; [[session uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"sesult---> %@ %@", result, [NSThread currentThread]); }] resume]; } - (NSString *)base64Encode:(NSString *)str { // 1. 将字符串转换成二进制数据 NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; // 2. 对二进制数据进行base64编码 NSString *result = [data base64EncodedStringWithOptions:0]; NSLog(@"base464--> %@", result); return result; }


    PUT方式与DELETE相应,DELETE用于删除PUT方式上传的文件。


    TIPS:session使用注意

    *网络会话, 方便程序猿使用网络服务.
    *:能够获得当前上传文件的进度.
    *NSURLSession的任务默认都是异步.(在其它线程中工作)
    *Task是由会话发起的.
    *注意网络请求都要进行出错处理.
    *session默认是挂起的, 须要resume一下才干启动.


    转载请注明出处:http://blog.csdn.net/xn4545945  

    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    输出三角行
    练习
    循环
    阶乘
    常量、变量、数据类型 搞错N+1次 累死
    UTF-8
    数据库事务
    Jsp的使用
    Cookie和Session
    请求转发和重定向
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4866588.html
Copyright © 2011-2022 走看看