博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
笔谈HTTP Multipart POST请求上传文件
阅读量:4588 次
发布时间:2019-06-09

本文共 5520 字,大约阅读时间需要 18 分钟。

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

1) 接口地址

接口地址为:

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:@[@"86000123456884846234123456789007"] 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[0]] 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:0];    [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];}

 

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

2015-05-08 10:10:11.834 PostDataToServer[4584:1627837] response: 

 

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

  完整工程PostDataToServer 的下载地址为:

 

转载于:https://www.cnblogs.com/sunminmin/p/4487042.html

你可能感兴趣的文章
android用户界面之Gallery3D学习资料汇总
查看>>
[编写高质量代码:改善java程序的151个建议]建议62 警惕数组的浅拷贝
查看>>
h5移动端适配iOS遇到的问题
查看>>
20. 最长公共子串(ToDo)[LCS]
查看>>
浮动:图解两栏布局
查看>>
CSS3 box-sizing 属性
查看>>
expect用法
查看>>
JavaScript [ 转 ] —— 面向对象编程(二):构造函数的继承
查看>>
$百度应用引擎BAE的使用与应用部署
查看>>
CodeForces Round #294 Div.2
查看>>
VHDL与Verilog硬件描述语言TestBench的编写
查看>>
leetcode 35. 搜索插入位置(Search Insert Position)
查看>>
内存使用和valgrind
查看>>
软件架构设计箴言理解
查看>>
建表过程与字符类型的意义
查看>>
事件绑定之bindEvent()与 unBindEvent()函数
查看>>
万能密码
查看>>
idea运行时默认显示的index.jsp修改方法
查看>>
1084 Broken Keyboard (20 分)
查看>>
winfrom获得鼠标的坐标
查看>>