简介

上传文件到服务器是一个比较常用的操作,最基本的方式是通过POST上传,文件以二进制形式,作为一个参数传递,但是这个POST的结构相当复杂,且必须完全符合HTTP标准。

文件上传的POST格式

该POST主要由下面几个部分构成。

  • 请求头

    1.Content-Length(请求体的二进制大小)

    • 注意这里的二进制大小应该根据请求体计算

    2.Content-Type multipart/form-data; boundary=(分隔符)

    • 注意这里的分隔符与请求体的分隔符有关,但不完全一致。
  • 请求体

    基本格式示例

    • 这里的分隔符就是上面的分隔符,但是前面要多加两个'-'
    --分隔符
    Content-Disposition: form-data; name="uploadFile"; filename="button.png"
    Content-Type: image/png
    (此处空两行)
    <二进制内容>
    --分隔符
    Content-Disposition: form-data; name="submit"
    (此处空两行)
    Submit
    --分隔符--
    (此处空一行)
    • 注意到最后的分隔符后面跟了--,这个代表结束符,并且后面要跟一个空行。

    格式说明

    • 普通参数

      普通参数的构成如下:

      Content-Disposition: form-data; name="参数名"
      (此处空两行)
      参数值
      --分隔符

      多个参数可以连续拼接。

    • 文件参数

      文件参数与普通参数类似,只是多了一行MineType的说明,该说明告诉服务器文件的类型。

      Content-Disposition: form-data; name="uploadFile"; filename="button.png"
      Content-Type: image/png
      (此处空两行)
      <二进制内容>
      --分隔符

    将二者连起来就构成了完整的文件上传POST信息,到这里我们可以理解,该POST不仅发送了文件数据,还发送了一个参数。

文件上传的服务器php脚本

  • 要让post请求发挥作用,必须借助php脚本实现对post的处理,换句话说,我们的post请求应该发送给该php脚本,脚本的代码如下:(注意修改uploadPath为自己服务器想要接收文件的路径)

    <?php
    header("Content-type: text/html; charset=utf-8");
    // 配置文件需要上传到服务器的路径,需要允许所有用户有可写权限,否则无法上传!
    $uploadPath = '../uploads/'; $IOS_forKey=$_FILES["uploadFile"]; if ($IOS_forKey["error"] > 0) {
    echo "传入参数错误:" . $IOS_forKey["error"] . "<br />";
    } else {
    echo "文件: " . $IOS_forKey["name"] . "<br />";
    echo "类型: " . $IOS_forKey["type"] . "<br />";
    echo "大小: " . ($IOS_forKey["size"] / 1024) . " Kb<br />";
    echo "临时文件: " . $IOS_forKey["tmp_name"] . "<br />"; chmod($uploadPath . $IOS_forKey["name"], 0666);
    if (file_exists($uploadPath . $IOS_forKey["name"])) {
    echo $IOS_forKey["name"] . "文件已经存在!";
    } else {
    move_uploaded_file($IOS_forKey["tmp_name"], $uploadPath . $IOS_forKey["name"]);
    echo "上传文件保存在: " . $uploadPath . $IOS_forKey["name"];
    }
    }
    ?>

通过iOS设备上传文件

想要通过iOS设备上传文件,一般的做法是根据上面的结构创建URLRequset,然后发送该request到服务器请求上面的php脚本,实现文件的上传,具体的代码如下。

  • 为了方便插入二进制文件数据,我们直接使用data拼接,因此对于每一段字符串都需要转为data,这就是DataWithStr宏的作用。

  • 为了适配各个系统的换行符,使用\r\n。

  • FileBoundary就是上文提到的分隔符。

  • HTTP请求头的contentLength需要待请求体拼接完毕后才能得到,因此最后才赋值。

#import "ViewController.h"
#import "UploadFile.h" #define FileBoundary @"-----------------------------test"
#define EndLine @"-----------------------------test--\r\n"
#define NewLine @"\r\n"
#define DataWithStr(str) [str dataUsingEncoding:NSUTF8StringEncoding] @interface ViewController () @end @implementation ViewController - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self upload]; } - (void)upload{ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1/lesson2/upload.php"]];
request.HTTPMethod = @"POST";
// 设置请求头
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",FileBoundary];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
// 设置请求体
NSMutableData *body = [NSMutableData data];
[body appendData:DataWithStr(@"--")];
[body appendData:DataWithStr(FileBoundary)];
[body appendData:DataWithStr(NewLine)];
[body appendData:DataWithStr(@"Content-Disposition: form-data; name=\"uploadFile\"; filename=\"test.png\"")];
[body appendData:DataWithStr(NewLine)];
[body appendData:DataWithStr(@"Content-Type: image/png")];
[body appendData:DataWithStr(NewLine)];
[body appendData:DataWithStr(NewLine)]; UIImage *img = [UIImage imageNamed:@"test.png"];
NSData *imgData = UIImagePNGRepresentation(img);
[body appendData:imgData];
[body appendData:DataWithStr(NewLine)]; // 其他参数
[body appendData:DataWithStr(@"--")];
[body appendData:DataWithStr(FileBoundary)];
[body appendData:DataWithStr(@"Content-Disposition: form-data; name=\"param1\"")];
[body appendData:DataWithStr(NewLine)];
[body appendData:DataWithStr(NewLine)];
[body appendData:DataWithStr(@"value1")];
[body appendData:DataWithStr(NewLine)];
[body appendData:DataWithStr(@"--")];
[body appendData:DataWithStr(EndLine)]; [request setValue:[NSString stringWithFormat:@"%ld",body.length] forHTTPHeaderField:@"Content-Length"]; request.HTTPBody = body; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",result);
}]; } @end

(一二八)使用POST上传文件的更多相关文章

  1. IE8/9 JQuery.Ajax 上传文件无效

    IE8/9 JQuery.Ajax 上传文件有两个限制: 使用 JQuery.Ajax 无法上传文件(因为无法使用 FormData,FormData 是 HTML5 的一个特性,IE8/9 不支持) ...

  2. 三种上传文件不刷新页面的方法讨论:iframe/FormData/FileReader

    发请求有两种方式,一种是用ajax,另一种是用form提交,默认的form提交如果不做处理的话,会使页面重定向.以一个简单的demo做说明: html如下所示,请求的路径action为"up ...

  3. asp.net mvc 上传文件

    转至:http://www.cnblogs.com/fonour/p/ajaxFileUpload.html 0.下载 http://files.cnblogs.com/files/fonour/aj ...

  4. app端上传文件至服务器后台,web端上传文件存储到服务器

    1.android前端发送服务器请求 在spring-mvc.xml 将过滤屏蔽(如果不屏蔽 ,文件流为空) <!-- <bean id="multipartResolver&q ...

  5. .net FTP上传文件

    FTP上传文件代码实现: private void UploadFileByWebClient() { WebClient webClient = new WebClient(); webClient ...

  6. 通过cmd完成FTP上传文件操作

    一直使用 FileZilla 这个工具进行相关的 FTP 操作,而在某一次版本升级之后,发现不太好用了,连接老是掉,再后来完全连接不上去. 改用了一段时间的 Web 版的 FTP 工具,后来那个页面也 ...

  7. 前端之web上传文件的方式

    前端之web上传文件的方式 本节内容 web上传文件方式介绍 form上传文件 原生js实现ajax上传文件 jquery实现ajax上传文件 form+iframe构造请求上传文件 1. web上传 ...

  8. Django session cookie 上传文件、详解

    session 在这里先说session 配置URL from django.conf.urls import patterns, include, url from django.contrib i ...

  9. 4 django系列之HTML通过form标签来同时提交表单内容与上传文件

    preface 我们知道提交表单有2种方式,一种直接通过submit页面刷新方法来提交,另一种通过ajax异步局部刷新的方法提交,上回我们说了通过ajax来提交文件到后台,现在说说通过submit来提 ...

随机推荐

  1. 页面中引入mui 地址选择,点击页面中其他input时页面回到顶部

    问题:在页面中引入mui地址选择时,点击页面中的input页面会滚到顶部(谷歌浏览器中出现的bug),在手机上点击input会出现跳动.开始的时候是想修改mui.min.js里的滚动事件,但是后来找到 ...

  2. Linux下 Apache Vhost 配置 防止403

    首先,贴一份正确的配置(最简单的) <VirtualHost *:80> DocumentRoot /home/ubuntu/www/spider/public ServerName sp ...

  3. mysql 从聚合函数group by到sql_mode

    说到group by, 想必大家都不陌生, 就是对查询的数据进行分组,我们可以通过该操作实现一些特殊需求,比如去重. 最近在项目中使用HQL:" from TSjrz where CBh = ...

  4. [Codeforces 946G]Almost Increasing Array

    Description 题库链接 给你一个长度为 \(n\) 的序列 \(A\) .现在准许你删除任意一个数,删除之后需要修改最小的次数使序列单调递增.问最小次数. \(1\leq n\leq 200 ...

  5. UVA 5009 Error Curves

    Problem Description Josephina is a clever girl and addicted to Machine Learning recently. She pays m ...

  6. BZOJ 1510: Kra-The Disks

    Johnny 在生日时收到了一件特殊的礼物,这件礼物由一个奇形怪状的管子和一些盘子组成. 这个管子是由许多不同直径的圆筒(直径也可以相同) 同轴连接而成. 这个管子的底部是封闭的,顶部是打开的. 下图 ...

  7. ●BZOJ 1416 [NOI2006]神奇的口袋

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1416题解: Pòlya瓦罐模型: 给定罐子里每种颜色的球的个数A[i],按题目要求随机操作若 ...

  8. poj 3384 半平面交

    Feng Shui Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5183   Accepted: 1548   Speci ...

  9. hdu 5645 DZY Loves Balls

    DZY Loves Balls  Accepts: 659  Submissions: 1393  Time Limit: 4000/2000 MS (Java/Others)  Memory Lim ...

  10. bzoj3295[Cqoi2011]动态逆序对 树套树

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5987  Solved: 2080[Submit][Sta ...