AFNetworking 2.0 多部分请求正文空白

2023-12-22

如同这个问题 https://stackoverflow.com/questions/20774692/afnetworking-multipart-request-body-is-nil.

使用 AFNetworking 2.0.3 并尝试使用 AFHTTPSessionManager 的 POST + ConstructionBodyWithBlock 上传图像。由于未知的原因,当向服务器发出请求时,HTTP 帖子正文似乎始终为空。

我在下面继承了 AFHTTPSessionManager (因此使用[self POST ...].

我尝试过以两种方式构建请求。

Method 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);
    }];
}

Method 2:尝试在块本身中构建表单数据:

- (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 标头。

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 的 github 存储库 https://github.com/AFNetworking/AFNetworking/issues/1732.


罗布是绝对正确的,你看到的问题与(现已关闭)有关第1398期 https://github.com/AFNetworking/AFNetworking/issues/1398。然而,我想提供一个快速的tl;dr,以防其他人在寻找。

首先,这是由github 上的 gberginc https://github.com/gberginc您可以根据以下方式对文件上传进行建模:

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];
                                                    }];

其次,总结一下问题(以及为什么必须使用临时文件作为解决方法),它确实有两个方面。

  1. Apple 认为内容长度标头在其控制之下,并且当为某个内容设置 HTTP 主体流时NSURLRequestApple 的库会将编码设置为 Chunked,然后放弃该标头(从而清除 AFNetworking 设置的任何内容长度值)
  2. 上传的服务器不支持Transfer-Encoding: Chunked(例如S3)

但事实证明,如果您从文件上传请求(因为提前知道总请求大小),Apple 的库将正确设置内容长度标头。疯狂吧?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AFNetworking 2.0 多部分请求正文空白 的相关文章

  • 从 Google/Facebook 帐户重新验证用户身份

    因此 我需要创建一个 REST API 来为 IOS 应用程序提供功能 我们允许用户仅使用普通帐户或使用脸书 谷歌登录 我最近一直在阅读 OAuth 我想我了解在我的情况下如何使用 OAuth 的过程 当用户使用脸书 谷歌登录 在我的应用程
  • 在 Alamofire 中快速发送 GET 请求中的 json 对象

    我正在尝试执行一个绑定了 json 对象的 GET 请求 这就是我生成 JSON 对象的方式 let jsonObject String AnyObject ean code type match value 16743799 然后我执行了
  • 创建宏来执行默认初始化

    我有很多重复这个简单样板的方法 id myObject if myObject self myObject myObject class new return myObject 所以我想用一个简单的宏来替换它 define default
  • iOS 新手。预期的表达错误?

    这看起来很不寻常 因为该方法与我的 showAnswer 方法完全相同 所以我想我应该在这里问 import QuizViewController h interface QuizViewController end implementat
  • 如果您查看内部,nib 文件到底是什么样子的?

    我刚刚学习 nibs 和 swift 并对某些东西感到好奇 我知道 如果您有一个 main storyboard 文件 则首先加载根视图控制器的笔尖 然后加载该视图控制器下可能分层存在的任何视图 但是 我想知道一些事情 当他们说笔尖已 加载
  • 即席分发失败

    我在一家大公司工作 正在开发一个适用于 iOS 5 的 iOS 应用程序 分发应用程序的唯一方式是通过临时部署 我拥有自己的服务器已经有一段时间了 由 o2switch 法国托管商 托管 当我开始开发时 我们使用它来部署应用程序以进行 Be
  • 快速找到一个数字的下一个倍数的方法

    我需要找到从基数开始的数字的第一个倍数 例如 7 中 3 的第一个倍数是 9 我的第一次尝试是这样做 multiple baseNumber while multiple number 0 multiple 最后 multiple 将具有第
  • NSMutableData 删除字节?

    我可以使用以下命令轻松地将字节添加到 NSMutableData 实例appendData方法 但是我没有看到任何类似的删除数据的方法 我是否忽略了某些内容 或者我是否需要创建一个新对象并仅复制我需要的字节 请参阅以下方法的文档 void
  • 让约束在尺寸类别中发挥作用

    所以 我正在 Xcode 6 beta 中尝试尺寸类 我对图像设置了一些限制 使其根据 iPhone 纵向和横向对应的尺寸类别处于不同的位置 这些限制在下图中可见 正如您所看到的 当我处于紧凑 紧凑状态时 一些约束被 安装 而其他约束则没有
  • Swift NotificationCenter 删除观察者最快的方法

    我正在添加一些观察员viewController applicationWillResignActive applicationDidEnterBackground 以及许多其他人 我想删除self作为一行中所有已注册通知的观察者 我的问题
  • 处理 NSPropertyListSerialization 中的 CFNull 对象

    在我的应用程序中 我尝试序列化服务器响应字典并将其写入文件系统 但对于某些响应 我收到错误 属性列表格式无效 原因是服务器响应中的 CFNull 对象 现在 服务器响应将不断变化 因此我没有明确的方法来删除 CFNull 对象 下面是我的代
  • iOS 复合谓词

    我正在编写一个具有照片数据库的应用程序 每张照片都有多个与之关联的标签 并且该应用程序有一个带有大量切换的搜索页面 允许用户仅根据他们感兴趣的标签搜索照片 每个标签都存储了integerID 是因为它们对应于外部数据库的 ID 所以我尝试简
  • 连接到 Apple Music

    所以我尝试使用 React Native 应用程序从 iOS 设备连接到 Apple Music 有一个 API 可以执行相同的操作 但我需要从 storekit 框架调用一个函数 提出个性化请求 苹果音乐API https develop
  • Xcode 本地化设置中没有加号或减号按钮

    我需要在两天内翻译 iOS 应用程序 但我的 XCode 版本 4 4 和 4 5 Developer Preview 都没有给我添加其他语言的选项 我只能选择单击 Make localized 但我只能选择英语 选择它后 Xcode 中的
  • 为什么 iOS 5.0 不喜欢纯窗口应用程序?为什么它要求使用视图控制器?

    我有一个使用 Xcode 4 0 的 基于窗口的应用程序 模板创建的 iOS 应用程序 当时运行良好 并且使用的是 iOS 4 3 SDK 这是一个简单地将按钮 标签等直接放置到窗口上的应用程序 没有视图控制器 什么都没有 但现在我已经升级
  • 子视图控制器旋转方法未被调用

    Summary 我试图将子视图控制器添加到父视图控制器 并让父视图控制器通知子视图控制器旋转事件 但是 旋转消息不会转发到子视图控制器 这是默认行为 为什么这种默认行为没有发生 环境 iOS 7 XCode 5 OSX 10 9 Detai
  • iOS 11 getUserMedia 不起作用?

    苹果公司发表声明称getUserMedia将在 iOS 11 上完全正常运行 安装 iOS 11 Beta 版本 5 后 我确实收到一条消息 表明我的网站请求访问我的相机和麦克风 但似乎是这样的 video src window URL c
  • extern NSString *const 在类中。

    你好 我有这个头文件 import
  • 更新查询时 ios 中出现“数据库锁定”错误

    我正在使用下面的代码更新查询 using sqlite 但我越来越 database is locked error 我尝试搜索一些 SO 链接 建议关闭数据库 但我再次执行此操作时遇到相同的错误 我已经提到过代码中出现错误的地方 cons
  • 如何将 NSAppTransportSecurity 添加到 Cordova 项目

    我正在从事一个 ionic cordova 项目 该应用程序需要配置 iOS 9 版本的应用程序传输安全例外 有谁知道如何将以下配置添加到 cordova 项目配置文件中 配置 xml

随机推荐

  • 将android库发布到jcenter:gradle bintrayUpload找不到库

    我正在尝试将 Android 库发布到 jcenter 我已经关注了https github com danielemaddaluno gradle jcenter publish https github com danielemadda
  • 只有一个实例可与 IIS7.5 上的 Azure October 2012 SDK 配合使用

    我刚刚将我的 Azure 解决方案升级到 VS2012 和 2012 年 10 月版本 我有 2 个 webrole 但当我从 IIS 管理器查看时 其中只有 1 个正在工作 我确信这一点 因为我的网络角色的角色间通信请求也失败了 首先我认
  • 如何将 FragmentTabhost 放在底部

    我想把 tabwidget 像 iPhone App 一样放在底部 我知道这个布局违反了 Google 用户界面指南 但我需要 所以 我在 Stackoverflow 上读过很多类似的帖子 但每个帖子都不起作用 我想使用 FragmentT
  • 适用于 iPhone 的 C 与 C++(Objective-C 与 Objective-C++)

    我想为 iPhone 创建一个便携式库 也可以用于其他平台 我的问题如下 有谁知道 iPhone 上最好用的是什么 Objective C 或 Objective C 它与 C 的工作方式是否与 Objective C 与 C 的工作方式相
  • Shell 导航底部和上部 TabBar 滚动行为

    在后续的shell 导航栏滚动行为 https stackoverflow com questions 65544512 shell navigation bar scroll behavior 我创建了一个具有滚动行为的自定义 Shell
  • 检查单元格是否包含子字符串

    是否有内置函数来检查单元格是否包含给定的字符 子字符串 这意味着您可以应用文本函数 例如Left Right Mid当分隔字符不存在时 有条件地不会抛出错误 尝试使用这个 ISNUMBER SEARCH Some Text A3 这将返回T
  • SceneKit – 获取相机方向

    我需要找出相机正在看哪个方向 例如如果它正在寻找Z Z X or X 我尝试过使用eulerAngles 但偏航范围为0 gt 90 gt 0 gt 90 gt 0这意味着我只能检测相机是否朝向Z or X 如果它朝这些轴的正方向或负方向看
  • 如何在 ASPnet Identity 中通过 Linq 检索具有特定角色的用户

    我需要检索特定角色的所有用户 我认为应该简单明了 但是 这就是问题所在 ApplicationUser的角色导航属性不是角色列表 IdentityRole 而是链接用户和角色的中间表 IdentityUserroles 的集合 所以 这是我
  • 在 Amazon Lambda 上运行 Spring Boot

    我正在尝试在 Amazon Lambda 上部署 Spring Boot 应用程序 我注意到 如果处理程序被快速连续调用 spring 会尝试重新加载自身 重新设置数据源 重新加载 bean 等 如果 main 方法已经被调用 是否有办法告
  • Oracle JDK安装两个JRE?

    在投反对票之前 or 关闭请求这个问题请看这个问题是关于 JDK 7 而不是 6 它有第二个问题 Q2 没有被任何重复的线程解决 这个问题是关于four不仅twojava exe 实例 谢谢你 我刚刚安装了 Oracle 的 Java SE
  • Egit 可以与现有 Eclipse 项目和现有 Git 存储库一起使用吗?

    我一直在使用 Eclipse 和 Git 现在我想使用EGit 我的项目有4个包 每个包都有一个 Git 存储库 当我将 Git 存储库导入 EGit 时 用户文档中有导入或创建 project 文件的说明 这些 project 文件可能与
  • 如何搜索自定义数据库表(不是 WordPress 表)?

    我有一个定价表 已导入到我的 WordPress 网站的架构中 现在我希望允许用户搜索该表并查看它 但不能编辑它 已经有插件了吗让我这样做吗 我发现 dbtoolkit 过于复杂 在这个简单的情况下不起作用 我尝试过其他几个插件 但它们似乎
  • strcpy是如何实现的?

    我有一个关于使用 strcpy 的问题 我知道 ANSI C 标准规定 源和目标不得重叠 否则行为是不可预测的 我向您展示了一段代码 如果它是在 Linux 下使用旧的 gnu C 编译器编译的 那么它可以按我的预期工作 include
  • 如何确定 LINQ 查询是 LINQ to SQL 还是 LINQ to Objects?

    通常 LINQ to SQL 和 LINQ to Objects 之间的区别并不是什么大问题 但如何确定发生的是哪一种情况呢 在编写代码时了解这一点很有用 但我担心有时只能在运行时才能确定 It s not微优化以区分 Linq To Sq
  • Java Thread.currentThread().setUncaughtExceptionHandler() 不适用于 JUNIT?

    在下面的示例代码中 如果 testMethod 通过 main 运行 它将按预期工作 但如果通过 JUNIT 运行 则不会调用 MyUncaughtExceptionHandler 这有什么解释吗 package nz co test im
  • 在android中如何将opengl纹理转换回位图?

    我想将图像过滤器应用于我的图像并使用Android HelloEffects 示例 https github com android platform development blob master samples HelloEffects
  • Numba 需要 NumPy 1.20 或更低版本才能导入 shapley

    我正在尝试导入形状 我遇到以下错误 我安装了较低版本的NumPy仍然问题没有解决 谢谢你 import shap ImportError Traceback most recent call last tmp ipykernel 22681
  • 使用 HTTP Post 并使用 Cookie

    我正在尝试使用 Go 登录网站并存储 cookie 以供以后使用 您能否给出用于发布表单 存储 cookie 以及使用 cookie 访问另一个页面的示例代码 我想我可能需要通过学习创建一个客户端来存储cookiehttp gotour g
  • 将过滤器选择调整/更新为闪亮的 DT 数据表中已应用的过滤器

    我正在使用 DT 包在 rshiny 中显示表格 当我在一列中应用过滤器时 其他列的过滤器选择不会适应已过滤的表 因此 在下面的示例中 如果您使用 4 3 4 8 过滤 sepal length 即使没有 sepal length 介于 4
  • AFNetworking 2.0 多部分请求正文空白

    如同这个问题 https stackoverflow com questions 20774692 afnetworking multipart request body is nil 使用 AFNetworking 2 0 3 并尝试使用