美文网首页Swift初体验iOS相机 / 相册 的入门文章iOS收集
iOS上传图像到服务器,以及服务器PHP接收的三种方式

iOS上传图像到服务器,以及服务器PHP接收的三种方式

作者: 阳光下慵懒的驴 | 来源:发表于2016-05-12 20:03 被阅读4298次

    1. 将图片转换为Base64编码,POST上传。PHP将Base64解码为二进制,再写出文件。

    缺点:不能上传较大的图片
    原因:post 理论上讲是没有大小限制的,HTTP协议规范也没有进行大小限制,但实际上post所能传递的数据量大小取决于服务器的设置和内存大小。以php语言来说,上传文件最大是默认是2MB,更改这个值需要更改php.conf的post_max_size这个值。

    // iOS(Swift)
    func upload(image: UIImage, url: String) {
        let imageData = UIImageJPEGRepresentation(image, 0.3) // 将图片转换成jpeg格式的NSData,压缩到0.3
        let imageStr = imageData?.base64EncodedStringWithOptions(.Encoding64CharacterLineLength) // 将图片转换为base64字符串
        let params: NSDictionary = ["file": imageStr!]
        let manager = AFHTTPRequestOperationManager()
        
        // 采用POST的方式上传,因为POST对长度没有限制
        manager.POST(url, parameters: params, success: { (_: AFHTTPRequestOperation!, response: AnyObject!) in
            // 成功
        }) { (_: AFHTTPRequestOperation!, _: NSError!) in
            // 失败
        }
    }
    
    <?php
    header('Content-type: text/json; charset=UTF-8');
    
    $base64 = $_POST["file"]; // 得到参数
    $img = base64_decode($base64); // 将格式为base64的字符串解码
    $path = "md5(uniqid(rand()))".".jpg"; // 产生随机唯一的名字作为文件名
    file_put_contents($path, $img); // 将图片保存到相应位置
    ?>
    

    2.AFNetworking上传,PHP端通过正常接收网页上传方法来接收图片

    static func uploadPortrait(image: UIImage, url: String) {
        let manager = AFHTTPRequestOperationManager()
        
        // fromData: AFN封装好的http header类,可以添加请求体
        manager.POST(url, parameters: [:], constructingBodyWithBlock: { (fromData: AFMultipartFormData!) in
            let pngData = UIImagePNGRepresentation(image)
            // name必须和后台PHP接收的参数名相同($_FILES["file"])
            // fileName为图片名
            fromData.appendPartWithFileData(pngData, name: "file", fileName: "image.png", mimeType: "image/png")      
              
            // let jpegData = UIImageJPEGRepresentation(image, 0.3)
            // fromData.appendPartWithFileData(jpegData, name: "file", fileName: "image.jpg", mimeType: "image/jpeg")
        }, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) in
            // 成功
        }) { (operation: AFHTTPRequestOperation!, error: NSError!) in
            // 失败
        }   
    }
    
    <?php
    header('Content-type: text/json; charset=UTF-8' );
    
    /**
     * $_FILES 文件上传变量,是一个二维数组,第一维保存上传的文件的数组,第二维保存文件的属性,包括类型、大小等
     * 要实现上传文件,必须修改权限为加入可写 chmod -R 777 目标目录
     */
    
    // 文件类型限制
    // "file"名字必须和iOS客户端上传的name一致
    if (($_FILES["file"]["type"] == "image/gif")
    || ($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/png")
    || ($_FILES["file"]["type"] == "image/pjpeg"))
    // && ($_FILES["file"]["size"] < 20000)) // 小于20k
    {
        if ($_FILES["file"]["error"] > 0) {
            echo $_FILES["file"]["error"]; // 错误代码
        } else {           
            $fillname = $_FILES['file']['name']; // 得到文件全名
            $dotArray = explode('.', $fillname); // 以.分割字符串,得到数组
            $type = end($dotArray); // 得到最后一个元素:文件后缀
    
            $path = "../portrait/".md5(uniqid(rand())).'.'.$type; // 产生随机唯一的名字
            
            move_uploaded_file( // 从临时目录复制到目标目录
              $_FILES["file"]["tmp_name"], // 存储在服务器的文件的临时副本的名称
              $path);
              
            echo "成功";
        } 
    } else {
        echo "文件类型不正确";
    }
    ?>
    
    

    3.将图片封装在Http的请求报文中的请求体(body)中上传。也是AFN上传的原理

    // 使用OC封装
    #import <UIKit/UIKit.h>
    @interface RequestPostUploadHelper : NSObject
    + (NSMutableURLRequest *)uploadImage:(NSString*)url uploadImage:(UIImage *)uploadImage params:(NSMutableDictionary *)params;
    @end
    
    #import "RequestPostUploadHelper.h"
    @implementation RequestPostUploadHelper
    + (NSMutableURLRequest *)uploadImage:(NSString*)url uploadImage:(UIImage *)uploadImage params:(NSMutableDictionary *)params {
        [params setObject:uploadImage forKey:@"file"];
        
        //分界线的标识符
        NSString *TWITTERFON_FORM_BOUNDARY = @"AaB03x";
        //根据url初始化request
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                               cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                           timeoutInterval:10];
        //分界线 --AaB03x
        NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
        //结束符 AaB03x--
        NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
        //要上传的图片
        UIImage *image=[params objectForKey:@"file"];
        //得到图片的data
        NSData* data = UIImagePNGRepresentation(image);
        //http body的字符串
        NSMutableString *body=[[NSMutableString alloc]init];
        //参数的集合的所有key的集合
        NSArray *keys= [params allKeys];
        
        //遍历keys
        for(int i = 0; i < [keys count]; i++)
        {
            //得到当前key
            NSString *key = [keys objectAtIndex:i];
            //如果key不是file,说明value是字符类型,比如name
            if(![key isEqualToString:@"file"])
            {
                //添加分界线,换行
                [body appendFormat:@"%@\r\n",MPboundary];
                //添加字段名称,换2行
                [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
                //添加字段的值
                [body appendFormat:@"%@\r\n",[params objectForKey:key]];
            }
        }
        
        ////添加分界线,换行
        [body appendFormat:@"%@\r\n",MPboundary];
        //声明file字段,文件名为image.png
        [body appendFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"image.png\"\r\n"];
        //声明上传文件的格式
        [body appendFormat:@"Content-Type: image/png\r\n\r\n"];
        
        //声明结束符:--AaB03x--
        NSString *end=[[NSString alloc] initWithFormat:@"\r\n%@",endMPboundary];
        //声明myRequestData,用来放入http body
        NSMutableData *myRequestData = [NSMutableData data];
        //将body字符串转化为UTF8格式的二进制
        [myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
        //将image的data加入
        [myRequestData appendData:data];
        //加入结束符--AaB03x--
        [myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
        
        //设置HTTPHeader中Content-Type的值
        NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
        //设置HTTPHeader
        [request setValue:content forHTTPHeaderField:@"Content-Type"];
        //设置Content-Length
        [request setValue:[NSString stringWithFormat:@"%d", [myRequestData length]] forHTTPHeaderField:@"Content-Length"];
        //设置http body
        [request setHTTPBody:myRequestData];
        //http method
        [request setHTTPMethod:@"POST"];
        
        return request;
    }
    @end
    
    
    // 使用
    // Swift
    static func uploadPortrait(image: UIImage, url:String) {
        // 使用
        let request = RequestPostUploadHelper.uploadImage(url, uploadImage: image, params: [:])
        // 异步网络请求
        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in
            if error != nil {
                // 失败
            } else {
                // 成功
            }
        }
    }
    
    <?php
    // PHP代码和上一步相同
    ?>
    

    4.iOS图片转换为NSData,通过POST上传。PHP接收POST参数,将NSData的16进制编码转换为PHP支持的二进制,再写出文件保存

    暂时没有找到办法,PHP接收到16进制编码后,使用算法转换为二进制后无法输出图片。在这里抛砖引玉,如果有同学知道解决办法,希望简信或者评论。

    5.二进制POST上传。PHP直接将数据保存为图片

    暂时没有找到办法,iOS端使用NSData的getBytes无法转换为二进制。在这里抛砖引玉,如果有同学知道解决办法,希望简信或者评论。

    相关文章

      网友评论

      • ipOhSp:写的不错,要是用OC就好了,最近一直在研究PHP,swift疏忽了,第一种用base64上传是最常用的吧...
        动感超人丶:@动感超人丶 swift也是不太会用
        动感超人丶:兄弟,php学的咋样了?我ios再转php和小程序

      本文标题:iOS上传图像到服务器,以及服务器PHP接收的三种方式

      本文链接:https://www.haomeiwen.com/subject/ifuprttx.html