我想将图像发布到服务器端Flask端点。我使用以下代码运行以下GET和POST,然后描述服务器接收的内容。如何确保服务器在POST请求中接收图像并发布参数?
[_client POST:@"post_image"
parameters:parameters
constructingBodyWithBlock:nil
success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog([responseObject description]);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog([error description]);
}
];
[_client GET:@"test_get"
parameters:parameters
success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog([responseObject description]);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog([error description]);
}
];
日志打印:
2014-07-02 10:29:06.883 lens-app[2808:60b] {
code = "";
data = "good stuff";
error = "";
success = 1;
}
2014-07-02 10:29:06.889 lens-app[2808:60b] {
code = "";
data = "good stuff";
error = "";
success = 1;
}
我使用此Flask代码来描述服务器收到的请求:
def print_request():
print 'request'
print str(request)
print 'request.headers'
print str(request.headers)
print 'request.args'
print str(request.args)
print 'request.form'
print str(request.form)
print 'request.files'
print str(request.files)
print 'request.data'
print str(request.data)
print 'request.stream'
print str(request.stream.read())
print 'request.environ'
print str(request.environ)
print 'request.get_json()'
print str(request.get_json())
print 'row post body'
print str(request.environ['body_copy'])
@app.route('/post_image', methods=['POST'])
def post_image():
print_request()
return json_response('good stuff')
@app.route('/test_get', methods=['GET'])
def test_get():
print_request()
return json_response('good stuff')
以下是发布请求的结果:
request
<Request 'http://ec2-xyz.us-west-2.compute.amazonaws.com/post_image' [POST]>
request.headers
Transfer-Encoding: Chunked
Content-Length:
User-Agent: lens-app/1.0 (iPhone; iOS 7.1.1; Scale/2.00)
Connection: keep-alive
Host: ec2-xyz.us-west-2.compute.amazonaws.com
Accept: */*
Accept-Language: en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5
Content-Type: multipart/form-data; boundary=Boundary+F841C4764BD7CE95
Accept-Encoding: gzip, deflate
request.args
ImmutableMultiDict([])
request.form
ImmutableMultiDict([])
request.files
ImmutableMultiDict([])
request.data
request.stream
request.environ
{'wsgi.multiprocess': False, 'SERVER_SOFTWARE': 'Werkzeug/0.9.6', 'SCRIPT_NAME': '', 'HTTP_TRANSFER_ENCODING': 'Chunked', 'REQUEST_METHOD': 'POST', 'PATH_INFO': '/post_image', 'SERVER_PROTOCOL': 'HTTP/1.1', 'QUERY_STRING': '', 'werkzeug.server.shutdown': <function shutdown_server at 0x2c45c80>, 'CONTENT_LENGTH': '', 'HTTP_USER_AGENT': 'lens-app/1.0 (iPhone; iOS 7.1.1; Scale/2.00)', 'HTTP_CONNECTION': 'keep-alive', 'SERVER_NAME': '0.0.0.0', 'REMOTE_PORT': 44640, 'wsgi.url_scheme': 'http', 'SERVER_PORT': '80', 'werkzeug.request': <Request 'http://ec2-54-214-166-2.us-west-2.compute.amazonaws.com/post_image' [POST]>, 'body_copy': '', 'wsgi.input': <cStringIO.StringI object at 0x2be5ad0>, 'HTTP_HOST': 'ec2-xyz.us-west-2.compute.amazonaws.com', 'wsgi.multithread': False, 'HTTP_ACCEPT': '*/*', 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7fccfbd3f1e0>, 'REMOTE_ADDR': '204.28.119.158', 'HTTP_ACCEPT_LANGUAGE': 'en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5', 'CONTENT_TYPE': 'multipart/form-data; boundary=Boundary+F841C4764BD7CE95', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate'}
request.get_json()
None
row post body
以下是获取请求的结果:
request
<Request 'http://ec2-xyz.us-west-2.compute.amazonaws.com/test_get?up=what's&you=Hey' [GET]>
request.headers
Content-Length:
User-Agent: lens-app/1.0 (iPhone; iOS 7.1.1; Scale/2.00)
Connection: keep-alive
Host: ec2-xyz.us-west-2.compute.amazonaws.com
Accept: */*
Accept-Language: en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5
Content-Type:
Accept-Encoding: gzip, deflate
request.args
ImmutableMultiDict([('you', u'Hey'), ('up', u"what's")])
request.form
ImmutableMultiDict([])
request.files
ImmutableMultiDict([])
request.data
request.stream
request.environ
{'wsgi.multiprocess': False, 'SERVER_SOFTWARE': 'Werkzeug/0.9.6', 'SCRIPT_NAME': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/test_get', 'SERVER_PROTOCOL': 'HTTP/1.1', 'QUERY_STRING': 'up=what%27s&you=Hey', 'werkzeug.server.shutdown': <function shutdown_server at 0x2c45c08>, 'CONTENT_LENGTH': '', 'HTTP_USER_AGENT': 'lens-app/1.0 (iPhone; iOS 7.1.1; Scale/2.00)', 'HTTP_CONNECTION': 'keep-alive', 'SERVER_NAME': '0.0.0.0', 'REMOTE_PORT': 33553, 'wsgi.url_scheme': 'http', 'SERVER_PORT': '80', 'werkzeug.request': <Request 'http://ec2-xyz.us-west-2.compute.amazonaws.com/test_get?up=what's&you=Hey' [GET]>, 'body_copy': '', 'wsgi.input': <cStringIO.StringI object at 0x2be5ad0>, 'HTTP_HOST': 'ec2-xyz.us-west-2.compute.amazonaws.com', 'wsgi.multithread': False, 'HTTP_ACCEPT': '*/*', 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7fccfbd3f1e0>, 'REMOTE_ADDR': '204.28.119.158', 'HTTP_ACCEPT_LANGUAGE': 'en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5', 'CONTENT_TYPE': '', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate'}
request.get_json()
None
row post body
答案 0 :(得分:0)
事实证明,AFNetworking only supports streaming multipart POST requests。我使用mod_wsgi服务器端,只有mod_wsgi版本3.0+开始支持分块HTTP传输。这是对Changes in Version 3.0的mod_wsgi列表中的更改的评论:
- 现在允许分块请求内容。这些内容将被删除并可供WSGI应用程序阅读。参见:
醇>http://code.google.com/p/modwsgi/issues/detail?id=1启用此功能 功能,您必须使用:
WSGIChunkedRequest打开Apache配置中的适当上下文。
请注意,WSGI在技术上无法支持 没有所有分块请求内容必须的分块请求内容 首先读入并缓冲。这是因为WSGI需要 当有任何请求内容时,设置CONTENT_LENGTH。
在mod_wsgi中没有缓冲完成。因此,能够读取请求 在分块传输编码的情况下,您需要步骤 在WSGI规范之外并且做它说你不是的事情 意思是。
您有两种选择可以做到这一点。第一选择你 有必要在wsgi.input上调用read()但不提供任何参数 所有。这将导致读入并返回所有请求内容。
第二个是循环使用set块调用wsgi.input上的read() size作为参数传递并执行此操作,直到read()返回空 字符串。
因为在WSGI规范下不允许这两种调用方法, 在使用这些代码时,您的代码将无法移植到其他WSGI主机 机制。
这是我使用的解决方法。我没有使用AFNetworking,因此我上传的图片没有流式传输。我找到了这段代码here。
- (NSString *)uploadImageData:(NSData *)imageData toURL:(NSURL *)url withTitle:(NSString *)title {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
// create a boundary to delineate the file
NSString *boundary = @"14737809831466499882746641449";
// tell the server what to expect
NSString *contentType =
[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
// make a buffer for the post body
NSMutableData *body = [NSMutableData data];
// add a boundary to show where the title starts
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary]
dataUsingEncoding:NSASCIIStringEncoding]];
// add the title
[body appendData:[
@"Content-Disposition: form-data; name=\"title\"\r\n\r\n"
dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[title
dataUsingEncoding:NSASCIIStringEncoding]];
// add a boundary to show where the file starts
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary]
dataUsingEncoding:NSASCIIStringEncoding]];
// add a form field
[body appendData:[
@"Content-Disposition: form-data; name=\"image\"; filename=\"image.jpeg\"\r\n"
dataUsingEncoding:NSASCIIStringEncoding]];
// tell the server to expect some binary
[body appendData:[
@"Content-Type: application/octet-stream\r\n"
dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[
@"Content-Transfer-Encoding: binary\r\n"
dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[[NSString stringWithFormat:
@"Content-Length: %i\r\n\r\n", imageData.length]
dataUsingEncoding:NSASCIIStringEncoding]];
// add the payload
[body appendData:[NSData dataWithData:imageData]];
// tell the server the payload has ended
[body appendData:
[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary]
dataUsingEncoding:NSASCIIStringEncoding]];
// add the POST data as the request body
[request setHTTPMethod:@"POST"];
[request setHTTPBody:body];
// now let's make the connection to the web
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
return [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
}