类似于this issue .
使用 AFNetworking 2.0.3 并尝试使用 AFHTTPSessionManager 的 POST + constructingBodyWithBlock 上传图像。由于未知原因,当向服务器发出请求时,HTTP post 正文似乎总是空白。
我在下面继承了 AFHTTPSessionManager(因此使用了 [self POST ...]。
我试过用两种方式构建请求。
方法 1:我只是尝试传递参数,然后只添加存在的图像数据。
- (void) createNewAccount:(NSString *)nickname accountType:(NSInteger)accountType primaryPhoto:(UIImage *)primaryPhoto
{
NSString *accessToken = self.accessToken;
// Ensure none of the params are nil, otherwise it'll mess up our dictionary
if (!nickname) nickname = @"";
if (!accessToken) accessToken = @"";
NSDictionary *params = @{@"nickname": nickname,
@"type": [[NSNumber alloc] initWithInteger:accountType],
@"access_token": accessToken};
NSLog(@"Creating new account %@", params);
[self POST:@"accounts" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
if (primaryPhoto) {
[formData appendPartWithFileData:UIImageJPEGRepresentation(primaryPhoto, 1.0)
name:@"primary_photo"
fileName:@"image.jpg"
mimeType:@"image/jpeg"];
}
} success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"Created new account successfully");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"Error: couldn't create new account: %@", error);
}];
}
方法 2:尝试在 block 本身中构建表单数据:
- (void) createNewAccount:(NSString *)nickname accountType:(NSInteger)accountType primaryPhoto:(UIImage *)primaryPhoto
{
// Ensure none of the params are nil, otherwise it'll mess up our dictionary
if (!nickname) nickname = @"";
NSLog(@"Creating new account %@", params);
[self POST:@"accounts" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFormData:[nickname dataUsingEncoding:NSUTF8StringEncoding] name:@"nickname"];
[formData appendPartWithFormData:[NSData dataWithBytes:&accountType length:sizeof(accountType)] name:@"type"];
if (self.accessToken)
[formData appendPartWithFormData:[self.accessToken dataUsingEncoding:NSUTF8StringEncoding] name:@"access_token"];
if (primaryPhoto) {
[formData appendPartWithFileData:UIImageJPEGRepresentation(primaryPhoto, 1.0)
name:@"primary_photo"
fileName:@"image.jpg"
mimeType:@"image/jpeg"];
}
} success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"Created new account successfully");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"Error: couldn't create new account: %@", error);
}];
}
无论使用哪种方法,当 HTTP 请求到达服务器时,都没有 POST 数据或查询字符串参数,只有 HTTP header 。
Transfer-Encoding: Chunked
Content-Length:
User-Agent: MyApp/1.0 (iPhone Simulator; iOS 7.0.3; Scale/2.00)
Connection: keep-alive
Host: 127.0.0.1:5000
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+0xAbCdEfGbOuNdArY
Accept-Encoding: gzip, deflate
有什么想法吗?还在 AFNetworking's github repo 中发布了错误.
最佳答案
Rob 完全正确,您看到的问题与(现已关闭)issue 1398 有关.但是,我想提供一个快速的 tl;dr,以防其他人在看。
首先,这是 gberginc on github 提供的代码片段您可以在以下之后对文件上传进行建模:
NSString* apiUrl = @"http://example.com/upload";
// Prepare a temporary file to store the multipart request prior to sending it to the server due to an alleged
// bug in NSURLSessionTask.
NSString* tmpFilename = [NSString stringWithFormat:@"%f", [NSDate timeIntervalSinceReferenceDate]];
NSURL* tmpFileUrl = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:tmpFilename]];
// Create a multipart form request.
NSMutableURLRequest *multipartRequest = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST"
URLString:apiUrl
parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath]
name:@"file"
fileName:fileName
mimeType:@"image/jpeg" error:nil];
} error:nil];
// Dump multipart request into the temporary file.
[[AFHTTPRequestSerializer serializer] requestWithMultipartFormRequest:multipartRequest
writingStreamContentsToFile:tmpFileUrl
completionHandler:^(NSError *error) {
// Once the multipart form is serialized into a temporary file, we can initialize
// the actual HTTP request using session manager.
// Create default session manager.
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
// Show progress.
NSProgress *progress = nil;
// Here note that we are submitting the initial multipart request. We are, however,
// forcing the body stream to be read from the temporary file.
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:multipartRequest
fromFile:tmpFileUrl
progress:&progress
completionHandler:^(NSURLResponse *response, id responseObject, NSError *error)
{
// Cleanup: remove temporary file.
[[NSFileManager defaultManager] removeItemAtURL:tmpFileUrl error:nil];
// Do something with the result.
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@", responseObject);
}
}];
// Add the observer monitoring the upload progress.
[progress addObserver:self
forKeyPath:@"fractionCompleted"
options:NSKeyValueObservingOptionNew
context:NULL];
// Start the file upload.
[uploadTask resume];
}];
其次,总结一下问题(以及为什么必须使用临时文件作为解决方法),它确实有两个方面。
NSURLRequest 设置 HTTP 正文流时,Apple 的库会将编码设置为 Chunked,然后放弃该 header (从而清除任何内容长度值 AFNetworking 集)Transfer-Encoding: Chunked(例如 S3)但事实证明,如果您从文件上传请求(因为请求的总大小提前已知),Apple 的库将正确设置内容长度 header 。疯了吧?
关于ios - AFNetworking 2.0 多部分请求正文空白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20956396/
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我使用rails3.1+rspec和factorygirl。我对必填字段(validates_presence_of)的验证工作正常。我如何让测试将该事实用作“成功”而不是“失败”规范是:describe"Addanindustrywithnoname"docontext"Unabletocreatearecordwhenthenameisblank"dosubjectdoind=Factory.create(:industry_name_blank)endit{shouldbe_invalid}endend但是我失败了:Failures:1)Addanindustrywithnona
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)
在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g