iOS上传文件,有关http上传协议-RFC1867

以上是抓包HTML input file标签上传的内容

只要模拟上面http 的header跟body就可以成功。

整体说明:

post 上传文件时,以在http body里面带参数,参数的格式,根据RFC1867协议要求写成如下

在http header 里面定义 boundary ,boundary的值为body里面分隔参数的标志。

Content-Type: multipart/form-data; boundary=----------LlcUploadTaskWithRequest

假设 post 过去,两个参数 user="loganv"&pwd="123456" 跟一个二进制文件 file,服务端通过字段 ‘file‘ 获取文件流,文件名字叫做filename.png。

------------LlcUploadTaskWithRequest
Content-Disposition: form-data; name="user"

loganv
------------LlcUploadTaskWithRequest
Content-Disposition: form-data; name="pwd"

123456
------------LlcUploadTaskWithRequest
Content-Disposition: form-data; name="file"; filename="filename.png"
Content-Type: application/octet-stream

ÿØÿàJFIFHHÿá¼ExifMM*JR(?i(此处为上传的二进制文件数据)
把下面这个体当成一对整体来看------------LlcUploadTaskWithRequest
Content-Disposition: form-data; name="user"

loganv

第一行:以header 里面定义的 boundary的值,在前面加"--",,以"\r\n"结尾

第二行:定义了参数的键 user ,以"\r\n"结尾

第三行:"\r\n"

第四行:参数的值 123456,以"\r\n"结尾

如果参数是文件,需要在上面的低二行下面增加一行定义文件的类型 MIME type

iOS 实现上传,swift2.0 主要代码

第一步:自定义boundary分割标志,在给header加个 Content-Type;

let post_boundary = "----------LlcUploadTaskWithRequest"

let reqq = NSMutableURLRequest(URL: NSURL(string: "http://172.16.0.199/upload/uploadIpa.php")!)

reqq.HTTPMethod = "POST"

reqq.setValue(post_boundary, forHTTPHeaderField: "Content-Type")

第二步:拼接http body 需要 post 过去的参数,跟二进制文件;服务端通过字段 ‘file‘ 获取文件流;

let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())var paramStr = ""

if param != nil{

for (k, v) in param!{

paramStr += uploadPostParamInBody(k, nameValue: v.description)

}

        }

paramStr += uploadPostParamInBody("file", filename: "filename.png")

        let boundary = paramStr.dataUsingEncoding(NSUTF8StringEncoding)?.mutableCopy() as? NSMutableData

let pdata = NSData(data: multipartFormData!)

let boundary_end = ("\r\n--" + post_boundary + "--").dataUsingEncoding(NSUTF8StringEncoding)

boundary?.appendData(pdata)

boundary?.appendData(boundary_end!)

拼接参数的方法

//---- uploadTaskWithRequest 上传
    /*
        name: post body里面带的参数的名称,服务器根据这个名称取得对应的参数值;
        filename: 文件的名字比如 logo.png;
        MIMEtyp: 为application/octet-stream代表任何二进制流都可以,图片传image/jpeg;

    */
    public func uploadPostParamInBody(name: String, filename: String = "", nameValue: String = "", MIMEtype: String = "application/octet-stream") -> String{
        var content = "--" + LlcHttpRequest.post_boundary + "\r\n"
        if filename == ""{
            content += "Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n";
            content += "\(nameValue)\r\n";
        }
        else{
            content += "Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(filename)\"\r\n";
            content += "Content-Type: \(MIMEtype)\r\n\r\n";
        }
        return content
    }

第三步:请求

let task = session.uploadTaskWithRequest(req.request, fromData: boundary){
            (obj: NSData?, resp: NSURLResponse?, err: NSError?) -> Void in
            if let respHtml = resp as? NSHTTPURLResponse {
                if respHtml.statusCode == 200 {
                    if obj != nil{
                        var resu: AnyObject? = String(data: obj!, encoding: NSUTF8StringEncoding)
                        if let json = try? NSJSONSerialization.JSONObjectWithData(obj!, options: .AllowFragments){
                            resu = json
                        }
                    }
                }
            }
            else{
                fail(resp: resp, error: err)
            }
            if err != nil{
                fail(resp: resp, error: err)
            }
        }
        task.resume()

完了!

附上PHP服务端简单接受文件上传的代码

<?php

  $text = isset($_REQUEST[‘text‘]) ? $_REQUEST[‘text‘] : "";
  echo ‘success<br>‘;
  if ($_FILES["file"]["error"] > 0){
    echo "Error: " . $_FILES["file"]["error"] . "<br />";
  }
  elseif ($_FILES["file"]["size"] > 20*1024*1024) {
    echo ‘file too big‘;
  }
  else{
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Stored in: " . $_FILES["file"]["tmp_name"] . ‘<br />‘;

    $isipa = false;
    $uploadSrc = ‘../download/ipa/‘.$_FILES["file"]["name"];
    if ( preg_match(‘/\.ipa$/‘, $_FILES["file"]["name"]) ) {
      $isipa = true;
      $uploadSrc = ‘../download/ipa/‘.‘test01.ipa‘;
    }

    if (file_exists($uploadSrc) && $isipa ){
      // echo $_FILES["file"]["name"] . " already exists. ";
      rename($uploadSrc, ‘../download/ipa/‘.date(‘Y-m-d H:i:s‘).‘.ipa‘);
    }
    move_uploaded_file($_FILES["file"]["tmp_name"], $uploadSrc);
    echo "Stored in: " . $uploadSrc.‘<br>‘;
    echo ‘上传成功!‘;
  }
时间: 2024-11-05 20:42:43

iOS上传文件,有关http上传协议-RFC1867的相关文章

PHP上传文件时无法上传成功,$_FILES[&#39;screenshot&#39;][&#39;tmp_name&#39;]为空

最近在学习<HeadFirst PHP & MySQL>一书的第5章"使用存储在文件中的数据",做一个文件上传的应用时,出现了错误,就是文件无法成功上传.这个问题困扰了我很久,不过还好最后终于解决了.原因是我上传的图片文件大小超过了HTML 表单中 MAX_FILE_SIZE 选项指定的值32768Bytes即32KB导致无法上传成功. 我使用了XAMPP(Apache + MySQL + PHP + Perl)集成开发包和Zend Studio 10.6作为PHP

使用HttpRequest.Files 获取上传文件,实现上传附件功能

使用HttpRequest.Files 获取上传文件,实现上传附件功能,不同浏览器会有差异: 获得在 Google 浏览器上传后得到的 HttpRequest.Files  (客户端上载文件的集合) 单个文件查看:对应的FileName 是上传文件的原始文件名:例:开发管理手册2017版.docx 获取IE浏览器上传后HttpRequest.Files: 单个文件查看:对应的FileName 是上传文件 带路径的文件名 例:C:\\Users\\XXX\\Desktop\\开发管理手册2017版

异步无刷新上传文件并且上传文件可以带上参数

关于异步上传文件并且带上参数,网上有很多关于这样的插件,而我最喜欢用的插件是ajaxfileupload.js,该插件的代码如下: /*   131108-xxj-ajaxFileUpload.js 无刷新上传图片 jquery 插件,支持 ie6-ie10    依赖:jquery-1.6.1.min.js   主方法:ajaxFileUpload 接受 json 对象参数   参数说明:   fileElementId:必选,上传文件域ID   url:必选,发送请求的URL字符串   fi

异步无刷新上传文件而且上传文件能够带上參数

关于异步上传文件而且带上參数,网上有非常多关于这种插件.而我最喜欢用的插件是ajaxfileupload.js.该插件的代码例如以下: /*   131108-xxj-ajaxFileUpload.js 无刷新上传图片 jquery 插件.支持 ie6-ie10    依赖:jquery-1.6.1.min.js   主方法:ajaxFileUpload 接受 json 对象參数   參数说明:   fileElementId:必选,上传文件域ID   url:必选,发送请求的URL字符串  

Flask-上传文件和访问上传的文件

 1.1.上传文件和访问上传的文件 upload_file_demo.py from flask import Flask,request,render_template import os from werkzeug.utils import secure_filename from flask import send_from_directory app = Flask(__name__) #新建images文件夹,UPLOAD_PATH就是images的路径 UPLOAD_PATH = o

Python下使用ftplib上传文件到ftp上

生产情况:tomcat下业务log备份,目录分多级,然后对应目录格式放到ftp上:所以,结构上 我就是一级一级目录进行判断(因为我没有找到在ftp一次判断其子目录是否存在),还有一个low点就是我没有找到怎样一次性的调用ftp的login因为现在每次判断都需要登录一下,最终功能是实现了:想着先贴出来 #!/usr/local/bin/python3.5 ###Description: 上传业务log到FTP199 ###Author: Tonny.Deng ###DateTime: 2016-1

ajax 上传文件,post上传文件,ajax 提交 JSON 格式的数据

ajax简介 前后台做数据交互 前后端做数据交互的方式(三种): (1)浏览器窗口输入地址(get的方式)(2)form表单提交数据(3)ajax提交数据 特点 特点: (1)异步 异步与同步的区别:同步是请求发过去,要等着回应:异步不需要等待,可以进行其他操作 (2)局部刷新 使用 使用: (1)url:匹配的路由 (2)type:发送的的方式 (3)data:发送的数据 (4)success:发送的数据成功回调条数 $('.btn').click(function () { $.ajax({

上传文件、ajax上传文件

一.普通上传文件 1 后台 from django.shortcuts import render,HttpResponse # Create your views here. def login(request): if request.method == 'GET': return render(request, 'login.html') def fileupload(request): myfile=request.FILES.get('myfile') with open(myfile

flume与kafka结合上传文件到HDFS上

实现如图的的效果(详细步骤请参考官方文档(http://flume.apache.org/FlumeUserGuide.html),flume更新版本比较快) flume1.conf的配置文件内容 a1.sources = r1 a1.sinks = k1 a1.channels = c1 #具体定义source a1.sources.r1.type = spooldir #先创建此目录,保证里面空的 a1.sources.r1.spoolDir = /logs #sink到kafka里面 a1

MultipartFile 动态决定是否上传文件,解决不上传文件报错

controller 接收参数   用 HttpServletRequest 代替 @RequestParam()  接收参数 picFile 前台 传文件的参数名字  ,   这样 前段 传 null  就可以  不必须 存文件了 MultipartFile picFile = null; boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart){ MultipartHttpSer