您的位置:首页 > 编程语言 > Python开发

iOS端向后台(Python-django)POST多块数据(multipart/form)

2014-03-06 18:00 543 查看

前端iOS向后端Django传输多模块数据


HTTP POST请求,发送multipart/form-data

为了能够理解在iOS端对post数据所做的包装,可以先阅读这样一篇文章:
HTTP请求基本介绍

阅读完上面这篇文章,就可以开始进行编写

//
//  EZHttpRequest.m
//
//  Created by apple on 14-3-6.
//  Copyright (c) 2014年 apple. All rights reserved.
//

#import "EZHttpRequest.h"
#define boundary @"---------------------------14737809831466499882746641449"
#define file_key @"docfile"
@implementation EZHttpRequest

+(NSData *)post:(NSArray *)content toURL:(NSURL *)post_url{
/*---------------------form of content data---------------------

1,Http header filed
Content-Type:multipart/form-data; boundary=@""
Content-Length:
2,content:
(1){boundary}
(2)Content-Disposition:form-data;name=@""
*(3)If data is not string,add:Content-Type:
(4)data
3,every line should end with '\r\n'

---------------------form of content data---------------------*/

//create url request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:post_url];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];

//set HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];

//set post data
NSData *post_body = [self pack:content];
[request setHTTPBody:post_body];

//set content length to HTTP header
[request setValue:[NSString stringWithFormat:@"%ld",[post_body length]] forHTTPHeaderField:@"Content-Length"];
//post request
NSError *error;
NSHTTPURLResponse *response = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
return result;
}

+(NSData *)pack:(NSArray *)content{
/*----------------form of content array----------------
(
{
parameter_name: @"",
parameter_data: NSData,
parameter_type: NSNumber:(text:0,file:1)

}dictionary

)array

----------------form of content array----------------*/
NSMutableData *postData = [NSMutableData data];
for(int i=0;i<content.count;i++){
NSDictionary *dic = [content objectAtIndex:i];
//boundary
[postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

//Content dispostion
NSNumber *type = [dic objectForKey:@"parameter_type"];
if([type integerValue] == 0){//text data
//parameter name
NSString *parameter_name = [dic objectForKey:@"parameter_name"];
NSString *name_string = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",parameter_name];
[postData appendData:[name_string dataUsingEncoding:NSUTF8StringEncoding]];

}else{//file data
NSString *parameter_name = [dic objectForKey:@"parameter_name"];
[postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", file_key,parameter_name] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}

//parameter data
NSData *parameter_data = [dic objectForKey:@"parameter_data"];
[postData appendData:parameter_data];

//end
[postData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}

[postData appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

return postData;
}

@end

为了方便以后的使用,将它写进了一个类中,需要时可以调用方法:

NSData *result = [EZHttpRequest post:array toURL:[NSURL URLWithString:@"http://url/"]];
这里的array是一个以字典为元素的数组,具体的array创建可以参见:

NSDictionary *username = [[NSDictionary alloc]initWithObjectsAndKeys:
@"parameter1",@"parameter_name",
[@"what's my name?" dataUsingEncoding:NSUTF8StringEncoding],@"parameter_data",
[NSNumber numberWithInteger:0],@"parameter_type",
nil];
NSDictionary *video = [[NSDictionary alloc]initWithObjectsAndKeys:
@"video.MOV",@"parameter_name",
videoData,@"parameter_data",
[NSNumber numberWithInteger:1],@"parameter_type",
nil];
NSArray *array = [[NSArray alloc]initWithObjects:username,video, nil];


其中parameter_type是为了方便控制后期post data的包装,可能很不成熟,日后有机会了再进行提升

如此一来,在后端可以通过键值"parameter1"得到这个字符数据,同样可以通过键值"docfile"得到上传的文件(这个docfile是在包装post data过程中,给文件数据模块定义的键值)

下面是Django端获取这些post的简单示例

Django project named 'video'

One app in project named 'upload'

Model in 'upload':

from django.db import models

class Video(models.Model):
v_video = models.FileField(upload_to='documents/%Y/%m/%d')


Views in 'upload':

from django.shortcuts import render
from models import Video
from upload.forms import DocumentForm
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def uploadMyVideo(request):
form = DocumentForm(request.POST,request.FILES)
if form.is_valid():
new = Video(v_video = request.FILES['docfile'])
new.save()
string = request.POST['username']
return HttpResponse(string)
return HttpResponse('not valid')


其中upload.forms是upload目录下的一个自创的forms.py文件,这个具体是参考Stackoverflow中一位同志的回答,具体这样写的理由有待发掘,下面是forms.py中的内容

# -*- coding: utf-8 -*-
from django import forms

class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file'
)


以上便是iOS向Django POST多块数据的例子,编码不太成熟,有待多多练习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  iOS Django post file http