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

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无法转换为二进制。在这里抛砖引玉,如果有同学知道解决办法,希望简信或者评论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,490评论 18 139
  • php.ini设置,上传大文件: post_max_size = 128Mupload_max_filesize ...
    bycall阅读 6,721评论 3 64
  • 该文章属于<简书 — Timhbw>原创,转载请注明: <简书社区 — Timhbw>http://www.jia...
    伯虔阅读 17,081评论 3 158
  • iOS开发系列--网络开发 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博、微信等,这些应用本身可...
    lichengjin阅读 3,617评论 2 7
  • 客户端JavaScript的作用: 客户端数据计算 表单输入验证 浏览器事件的触发和处理 网页特殊显示效果制作 服...
    喵小姐猫猫阅读 183评论 0 0