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:@"%@%@\n", boundaryStr, randomIDStr];
 [strM appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\n", uploadID, uploadFile];
 [strM appendFormat:@"Content-Type: %@\n\n", mimeType]; 

 NSLog(@"顶部字符串:%@", strM);
 return [strM copy];
} 

/** 拼接底部字符串 */
- (NSString *)bottomString
{
 NSMutableString *strM = [NSMutableString string]; 

 [strM appendFormat:@"%@%@\n", boundaryStr, randomIDStr];
 [strM appendString:@"Content-Disposition: form-data; name=\"submit\"\n\n"];
 [strM appendString:@"Submit\n"];
 [strM appendFormat:@"%@%@--\n", 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编码一下身份验证, session的upload一调用就行了.
*没有文件大小限制.
*即时通讯里面用的多.(发图片/发语音)

- (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一下才能启动.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue项目中使用axios上传图片等文件操作

    axios 简介 axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征: 从浏览器中创建 XMLHttpRequest 从 node.js 发出 http 请求 支持 Promise API 拦截请求和响应 转换请求和响应数据 取消请求 自动转换JSON数据 客户端支持防止 CSRF/XSRF 首先安装axios: 1.利用npm安装npm install axios –save 2.利用bower安装bower install axios

  • IOS开发教程之put上传文件的服务器的配置及实例分享

    1,HTTP常见的方法 GET 获取指定资源 POST 2M 向指定资源提交数据进行处理请求,在RESTful风格中用于新增资源 HEAD 获取指定资源头部信息PUT 替换指定资源(不支持浏览器操作)DELETE 删除指定资源 2,配置服务器的put请求方式: 复制代码 代码如下: 1> n 打开终端p cd /etc/apache2p sudo vim httpd.conf n 在vim中输入p /httpd-dav.conf• 查找httpd-dav.confp 按0将光标移动至行首 p 按

  • iOS开发中以application/json上传文件实例详解

    本文通过实例代码给大家讲解iOS中以application/json上传文件的形式,具体内容详情大家参考下本文. 在和sever后台交互的过程中.有时候.他们需要我们iOS开发者以"application/json"形式上传. NSString *accessUrl = [NSString stringWithFormat:@"%@/xxx",@"https://www.xxxxx.com:xxxx"]; NSMutableURLRequest

  • ios用AFN进行文件上传的示例代码

    App中个人信息页面,通常都会有设置头像的功能.当用户从相册中选择图像或者拍摄照片成功后,一般都需要将照片发送到服务器进行保存,以方便用户在其他设备或者再次登陆后,能再次从服务器请求到设置的照片.项目中通过AFN,实现起来很方便. - (void)upload{ NSData *imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mine.jpeg" ofType:nil

  • java接收ios文件上传的示例代码

    本文实例为大家分享了java如何接收ios文件上传的具体代码,供大家参考,具体内容如下 ios Multipart/form-data POST请求java后台spring接口一直出错,搞了两天,终于解决了,积累下来 package com.xx.controller; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator

  • iOS利用AFNetworking实现文件上传的示例代码

    0.导入框架准备工作 1. 将框架程序拖拽进项目 2.  添加iOS框架引用 –SystemConfiguration.framework –MobileCoreServices.framework 3.  引入 #import "AFNetworking.h" 4. 修改xxx-Prefix.pch文件 #import <MobileCoreServices/MobileCoreServices.h> #import <SystemConfiguration/Sys

  • iOS 断点上传文件的实现方法

    项目开发中,有时候我们需要将本地的文件上传到服务器,简单的几张图片还好,但是针对iPhone里面的视频文件进行上传,为了用户体验,我们有必要实现断点上传.其实也不是真的断点,这里我们只是模仿断点机制. 需求 既然需要上传文件,那最好要有一个上传列表界面,方面用户对上传中的文件进行实时管理.这里我简单搭建了一个上传列表界面,如下图: 该界面实现的功能:左滑删除,单击暂停.取消,清空列表.退出该界面可后台上传,暂停再次开始或则app被kill掉依旧支持续传.上传完成.删除正在上传文件.清空上传列表都

  • iOS开发中文件的上传和下载功能的基本实现

    文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: 复制代码 代码如下: YYViewController.m #import "YYViewController.h" #define YYEncode(str) [str dataUsingEncoding:NSUTF8StringEncoding] @interface YYV

  • iOS大文件的分片上传和断点上传的实现代码

    今天小编抽空给大家分享一些大文件的上传的问题!断点续传和分片上传.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传.所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这

  • vue使用axios实现文件上传进度的实时更新详解

    axios 简介 axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征: 从浏览器中创建 XMLHttpRequest 从 node.js 发出 http 请求 支持 Promise API 拦截请求和响应 转换请求和响应数据 取消请求 自动转换JSON数据 客户端支持防止 CSRF/XSRF 引入方式: $ npm install axios //使用淘宝源 $ cnpm install axios //或者使用cdn: <script s

  • Vue axios 中提交表单数据(含上传文件)

    我们经常使用表单来上传数据,以及上传文件,那么怎么在表单提交成功的时候接受服务器的响应,并作出相应操作. 当然使用一般jQuery上传对象的格式也是可以的,如果使用传统的表单上传呢? <!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport

  • iOS实现文件切片储存并且上传(仿断点续传机制)

    简介: 我们在开发中,一般在视频类的app或者与硬件交互的app中会有将数据文件上传到云端,少数社交app上传图片也比较多.下面讲的是将数据文件(txt类型)切片储存到本地并逐片上传到云端模仿断点续传的机制,但事实上,这个操作并不是真正的断点续传. google了一下,关于切分的文章也蛮多,但是都比较雷同,接下来要分享将数据写进txt并切片储存到本地,一片一片传到云端的整个流程.下面话不多说了,来一起看看详细的介绍吧. 步骤: 1.将获取到的数据写进文件(总文件) 2.将总文件按照需求分割并储存

随机推荐