公司一做iOS开发的同事用HTTP Multipart POST请求上传语音数据,但是做了两天都没搞定,项目经理找到我去帮忙弄下。以前做项目只用过get、post,对于现在这个跟服务器交互的表单请求我没有做过,但是程序员学习能力还是要有的,解决问题的方法和经验是很重要的。做过2000万用户量的业务sdk的开发,这点东西自然不在话下,优秀的程序员就是要有解决问题的能力与方法。

1) 接口地址

接口地址为:http://ip:port/upload

2) UploadRequest消息定义

Form表单参数定义如下

固定name属性为

参数名

参数类型

是否必填

描述

fileData

字符串变长

Y

标识为文件数据

其中的filename属性为

原始文件名

注意:该名称需要由上传端确保唯一性,此唯一只需要保证同一设备ID的情况下不重复即可

DevIDs

字符串变长

Y

设备ID(多个设备)

Transport

字符串变长

Y

音频编码信息,只支持G711A

ClientID

字符串变长

Y

客户端ID

3) UploadResponse消息定义

无扩展消息

举例

1) uploadRequest消息

POST /spi/mediaul.do HTTP/1.1

Accept: */*

Accept-Language: zh-cn

Content-Type: multipart/form-data; boundary=7da29f2d890386

Host: abc.com

Content-Length: 1516663(文件的实际总大小)

Connection: Keep-Alive

Cache-Control: no-cache

--7da29f2d890386

Content-Disposition: form-data; name="DevIDs";

660000000000000062349002a94658da, 66000000000000005550c42f9000e028

--7da29f2d890386

Content-Disposition: form-data; name="Transport";

PCMA/8000/1

--7da29f2d890386

Content-Disposition: form-data; name="ClientID";

XXXXXXX

--7da29f2d890386

Content-Disposition: form-data; name="fileData"; filename="XXX"

Content-Type: application/octet-stream

文件实际内容流数据

--7da29f2d890386--

2) uploadResponse消息

<?xml version="1.0" encoding="utf-8"?>

<Message Version="1.0">

<Header MsgType="UploadResponse" MsgSeq="11"/>

<Result RetCode="0" RetDesc="操作成功"/>

</Message>

  实现这个post表单请求,最重要的就是格式了,要知道 "\r\n" 与 "\n" 的区别,什么时候要换两行\r\n\r\n或多行\r\n\r\n\...,什么时候只能换一行\r\n,空格 不能漏掉,任何一个细节出现问题都会导致 the connection lost,这就是考察一个人的仔细程度。

  实现这个Multipart POST请求其实很简答的,细节决定成败,对于以前没有写个这种与服务器的表单交互请求的,那就只能在网上多搜集资料,认真比对了。所谓“熟读唐诗三百首,不会做诗也会吟”。我在网上看了一些资料,有的博客完全是误导人,这就要多看多对比,仔细甄别,做事与看人是同一道理,了解一个人不能凭一面之辞妄下结论。

  下面来看下我写的实现post与服务器进行表单数据交互的实现代码:

//
// Created by dev.temobi on 15/5/7.
// Copyright (c) 2015年 dev.temobi. All rights reserved.
// #import "ViewController.h" #define Boudary @"7da29f2d890386" //http://192.168.3.177:2800/upload
#define iAddrIP @"192.168.3.177"
#define iAddrPort 2800 @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. [self uploadAudioToServiceSelectedDevice:@[@""] delegate:self]; } - (void)uploadAudioToServiceSelectedDevice:(NSArray *)arrDevices delegate:(id)delegate//此delegate为 NSURLConnectionDelegate
{
NSString *url = [NSString stringWithFormat:@"http://%@:%i/upload",iAddrIP,iAddrPort]; NSMutableData *body = [ NSMutableData data ]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", Boudary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"DevIDs\"\r\n\r\n%@\r\n", arrDevices[]] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", Boudary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"Transport\"\r\n\r\n%@\r\n", @"PCMA/8000/1"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", Boudary] dataUsingEncoding:NSUTF8StringEncoding]];
NSString *TM_SDK_NULL_STRING = @"";
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"ClientID\"\r\n\r\n%@\r\n", TM_SDK_NULL_STRING] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", Boudary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"fileData\"; filename=\"aaaaa.pcma\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; // --注意只有一个\r\n
[body appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; // --注意有两个\r\n\r\n NSString *RecordAudioFilePath = [[NSBundle mainBundle] pathForResource:@"aaaaa" ofType:@"pcma"];
NSData *fileData = [NSData dataWithContentsOfFile:RecordAudioFilePath]; // ------语音数据---------
[body appendData:fileData];
[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", Boudary] dataUsingEncoding:NSUTF8StringEncoding]]; // ------注意分隔符Boudary前后各有一个\r\n--------- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
[request setTimeoutInterval:];
[request setValue:@"zh-cn" forHTTPHeaderField:@"Accept-Language"];
[request setValue:[NSString stringWithFormat:@"%lu",(unsigned long)body.length] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"];
[request setValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", Boudary] forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:body]; NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
if (data == nil) {
NSLog(@"send request failed: %@", error);
} [request release]; NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"response: %@", response);
    [response release];
}

  与服务器交互的响应结果如下:

-- ::11.834 PostDataToServer[:] response: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message>
<Header MsgSeq="" MsgType="UploadResponse"/>
<Result RetCode="2"/>
</Message>

  就是这么简单,语音数据成功上传给服务器了。

  完整工程PostDataToServer 的下载地址为:http://pan.baidu.com/s/1qWkKnta

笔谈HTTP Multipart POST请求上传文件的更多相关文章

  1. python中使用multipart/form-data请求上传文件

    最近测试的接口是上传文件的接口,上传单个文件,我主要使用了2种方法~ 接口例如: URL: http://www.baidu.com/*** method:post 参数: { "salar ...

  2. 解决python发送multipart/form-data请求上传文件的问题

    服务器接收文件时,有时会使用表单接收的方式,这意味着我们需要使用Python的requests上传表单数据和文件. 常用的方式一般如下: data = { 'name': 'nginx' } file ...

  3. SpringMVC实现PUT请求上传文件

    在JQuery中,我们可以进行REST ful中delete和put的请求,但是在java EE标准中,默认只有在POST请求的时候,servlet 才会通过getparameter()方法取得请求体 ...

  4. Postman Post请求上传文件

    Postman Post请求上传文件一.选择post请求方式,输入请求地址 二.填写Headers Key:Content-Type :Value:multipart/form-data 如下图 三. ...

  5. SSM框架下,使用ajax请求上传文件(doc\docx\excel\图片等)

    1.准备工作 1.1.添加上传必要jar包 <dependency> <groupId>commons-io</groupId> <artifactId> ...

  6. 使用python或robotframework调multipart/form-data接口上传文件

    这几天调一个multipart/form-data类型的接口,遇到点小阻碍.之前同事有使用urllib库写了个类似的方法实现,比较长,想要改的时候发现不太好使.在网上查找发现用requests库做这个 ...

  7. Unable to find ‘struts.multipart.saveDir’ Struts2上传文件错误的解决方法

    Unable to find ‘struts.multipart.saveDir’ Struts2上传文件错误的解决方法 在使用struts2的项目中上传文件的时候出现了一个这样的错误: 2011-7 ...

  8. element-ui上传组件,通过自定义请求上传文件

    记录使用element-ui上传组件,通过自定义请求上传文件需要注意的地方. <el-upload ref="uploadMutiple" :auto-upload=&quo ...

  9. JAVA模拟HTTP post请求上传文件

    在开发中,我们使用的比较多的HTTP请求方式基本上就是GET.POST.其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等.而我们在使用HTTP请求时中遇到的比较 ...

随机推荐

  1. 从 SVN 迁移至 Git 并保留所有 commit 记录

    yum install -y git-svn 用户映射文件user.txt,等号左边为svn账号,右边为Git用户名和邮箱.注意:svn中有多少用户就要映射多少 test1=test1<1472 ...

  2. 使用innobackupex进行mysql的差异备份还原和延迟复制

    使用innobackupex进行mysql的差异备份还原和延迟复制 背景: 有同事执行update语句没有添加where条件,导致大量脏数据,需要将这张表恢复到前一天 数据库上有备份,每周一次完整备份 ...

  3. CSAGAN的几大重点 - 2

    1.生成器 1)MRU(SketchyGAN) 计算过程为: 与DCGAN[46]和ResNet生成架构的定性和定量比较可以在5.3节中找到.MRU块有两个输入:输入特征图xi和图像I,输出特征图yi ...

  4. phpspreadsheet

    2019-5-9 8:20:07 星期四 昨天在看PHPExcel的时候, github上作者说已经停止更新了, 推荐使用phpspreadsheet, 查看了一下官方文档, 功能还挺强大的, 可以读 ...

  5. Cassandra开发入门文档第二部分(timeuuid类型、复合主键、静态字段详解)

    timeuuid类型 timeuuid具有唯一索引和日期时间的综合特性,可以与日期和时间函数联合使用,常用的关联函数: dateOf() now() minTimeuuid() and maxTime ...

  6. ShenZhenXiaoLengHuanYou Technology Co.,Ltd 技术支持网站

    本网页为ShenZhenXiaoLengHuanYou Technology Co.,Ltd 团队的技术支持网址,如果在我们开发的游戏中遇到任何问题,欢迎联系我们! QQ:2535510006 邮箱: ...

  7. java 快速定位线上cpu偏高

    1.top -c 加 大写P 查找高进程ID 2.top -Hp 加 大写 P 查找高线程ID 3.printf '%x\n' 线程ID 转成16进制 4.jstack 进程ID | grep 16进 ...

  8. Java后台使用httpclient入门HttpPost请求(form表单提交,File文件上传和传输Json数据)

    一.HttpClient 简介 HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 ...

  9. Resharper速度慢解决办法

    Reshaper很好用,但是安装后速度特别慢,大部分情况下,我们只需要使用一些插件功能,代码自动分析功能可以关闭,如图:取消Code analysis即可.

  10. Java开发笔记(一百四十三)FXML布局的基本格式

    前面介绍了JavaFX的常见控件用法,虽然JavaFX控件比起AWT与Swing要好用些,但是一样通过代码编写控件界面,并没有提高什么开发效率.要想浏览界面的展示效果,都必须运行测试程序才能观看,即使 ...