AFNetworking 3.0+中使用body传数据

本文介绍在AFNetworking3.0+中如何使用BODY方式传递数据,特别是从AFHTTPRequestOperationManager迁移到AFHTTPSessionManager时遇到的问题及解决办法。

AFNetworking 3.0+中使用body传数据

此篇是接着上一篇 iOS PBEwithMD5andDes加密解密算法,由于刚从AFNetworking2.0+升级到了3.0+,由AFHTTPRequestOperationManager改为AFHTTPSessionManager,还是照着以前的写法改一改网络请求工具类,然后把NSData数据加到body里面,发现服务器端死活收不到,被这个问题卡了大半天都没辙。后面终于在网上看到了一个替代方案,就是使用AFURLSessionManager这玩意搞定了问题。

废话不多说,直接上代码:

/**
 *  异步POST请求:以body方式,支持数组
 *
 *  @param url     请求的url
 *  @param body    body数据
 *  @param show    是否显示HUD
 *  @param success 成功回调
 *  @param failure 失败回调
 */
- (void)postWithUrl:(NSString *)url body:(NSData *)body showLoading:(BOOL)show success:(void(^)(NSDictionary *response))success failure:(void(^)(NSError *error))failure
{
    WS(weakSelf);
    if (show) {
        [weakSelf showLoading];
    }
    NSString *requestUrl = [NSString stringWithFormat:@"%@%@", kBaseUrl, url];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:requestUrl parameters:nil error:nil];
    request.timeoutInterval= TIME_OUT_INTERVAL;
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    // 设置body
    [request setHTTPBody:body];

    AFHTTPResponseSerializer *responseSerializer = [AFHTTPResponseSerializer serializer];
    responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",
                                                                      @"text/html",
                                                                      @"text/json",
                                                                      @"text/javascript",
                                                                      @"text/plain",
                                                                      nil];
    manager.responseSerializer = responseSerializer;

    [[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {

        if (!error) {
            if (show) {
                [weakSelf dismissLoading];
            }
            success([weakSelf processResponse:responseObject]);

        } else {
            failure(error);
            [weakSelf showErrorMessage];
            ILog(@"request error = %@",error);
        }
    }] resume];
}

需要注意的是HTTP头信息可能会根据服务器的要求做相应的修改。搞定!

<think>我们正在讨论Retrofit 3.0(实际上Retrofit 3.0已经比较旧,但问题指定了版本)。在Retrofit中,构建RequestBody通常用于POST、PUT等请求中,将数据作为请求体发送。 在Retrofit 3.0中,我们可以使用以下方式构建RequestBody: 1. 直接使用`RequestBody`类创建。 2. 通过Retrofit的转换器(如Gson)自动将对象转换为RequestBody(通常我们定义接口方法时使用特定的注解和参数类型,Retrofit会自动处理)。 但是,如果我们需要手动构建一个RequestBody(例如,发送纯文本、JSON字符串、文件等),可以使用`RequestBody`的静态方法。 常见场景: 1. 发送文本:`RequestBody.create(MediaType.parse("text/plain"), "my text");` 2. 发送JSON:`RequestBody.create(MediaType.parse("application/json"), jsonString);` 3. 发送文件:`RequestBody.create(MediaType.parse("image/png"), file);` 在Retrofit接口方法中,我们可以使用`@Body`注解来标记一个参数为请求体,该参数类型可以是`RequestBody`,也可以是其他可以被转换器转换的对象。 示例(接口定义): ```java public interface MyService { @POST("user") Call<ResponseBody> updateUser(@Body RequestBody body); } ``` 然后我们可以这样调用: ```java RequestBody body = RequestBody.create(MediaType.parse("application/json"), "{\"name\":\"John\"}"); Call<ResponseBody> call = service.updateUser(body); ``` 另外,在Retrofit 3.0中,我们还可以使用`okhttp3.RequestBody`(因为Retrofit 3.0依赖于OkHttp 3.x)。 注意:在较新的Retrofit版本中,`RequestBody.create`方法有所变化(例如,在Retrofit 2.6.0+和OkHttp 4.0+中,由于MediaType不再需要解析,而是直接使用常量,并且create方法有重载)。但问题指定Retrofit 3.0,所以使用方式如上。 更新:在Retrofit 3.0(OkHttp 3.x)中,`RequestBody.create`方法有两个参数:第一个是MediaType,第二个是内容(可以是String、byte数组、ByteString或File)。 因此,回答用户问题:在Retrofit 3.0中构建RequestBody,主要使用`okhttp3.RequestBody`的静态方法`create`。 但是,如果用户是在Kotlin中,代码类似,只是语法不同。 示例(Kotlin): ```kotlin val json = "{\"name\":\"John\"}" val requestBody = RequestBody.create(MediaType.parse("application/json"), json) ``` 另外,如果使用Gson转换器,我们通常不需要手动构建RequestBody,而是直接递一个对象,例如: ```kotlin data class User(val name: String) val user = User("John") // 然后在接口方法中直接使用@Body user: User ``` 所以,总结:手动构建RequestBody使用`RequestBody.create`方法,并指定媒体类型和内容。 现在,根据要求,在回答后必须提出3-5个相关问题,并以“§§相关问题§§”开头,然后列出问题。</think>### Retrofit 3.0 构建 RequestBody 的完整指南 在 Retrofit 3.0 中,`RequestBody` 是处理非表单数据(如 JSON、文件等)的核心类。以下是主要构建方式: #### 1. **文本数据构建** ```kotlin // 纯文本 val textBody = RequestBody.create(MediaType.parse("text/plain"), "Hello Retrofit") // JSON 数据 val json = "{\"name\":\"John\", \"age\":30}" val jsonBody = RequestBody.create(MediaType.parse("application/json"), json) ``` #### 2. **文件上** ```kotlin val file = File("/path/to/image.jpg") val fileBody = RequestBody.create(MediaType.parse("image/jpeg"), file) ``` #### 3. **多部分表单数据** ```kotlin val multipartBody = MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("username", "john_doe") .addFormDataPart("avatar", "profile.jpg", fileBody) // 使用前面创建的文件体 .build() ``` #### 4. **字节流数据** ```kotlin val byteArray = "Raw bytes data".toByteArray() val byteBody = RequestBody.create(MediaType.parse("application/octet-stream"), byteArray) ``` #### 5. **动态媒体类型** ```kotlin fun createDynamicBody(content: String, mimeType: String): RequestBody { return RequestBody.create(MediaType.parse(mimeType), content) } // 使用示例 val xmlBody = createDynamicBody("<node>value</node>", "application/xml") ``` #### 接口中使用示例 ```kotlin interface ApiService { @POST("upload") fun upload(@Body body: RequestBody): Call<ResponseBody> @Multipart @POST("profile") fun updateProfile(@Part("avatar") image: RequestBody): Call<ResponseBody> } // 调用示例 val call = retrofit.create(ApiService::class.java) .upload(jsonBody) ``` #### 关键注意事项: 1. 必须指定正确的 `MediaType`(MIME 类型) 2. 使用 `@Body` 注解标记请求体参数 3. 多部分数据需配合 `@Multipart` 接口注解 4. 文件上使用 `application/octet-stream` 或具体类型(如 `image/jpeg`) 5. Retrofit 3.0 使用 `okhttp3.RequestBody`(包路径:`okhttp3.RequestBody`)
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值