You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WKURLSchemeHandler是否支持XMLHTTPRequest携带的FormData请求体?

WKURLSchemeHandler本身支持将FormData作为请求体,你遇到的HTTPBody、HTTPBodyStream为nil的问题是WebKit针对自定义scheme的POST请求的默认优化逻辑导致的,不是功能不支持。

根因说明
  • WKWebView的网络请求处理默认在独立的WebKit进程中执行,为了避免大体积请求体多次跨进程拷贝带来的内存开销,WebKit对自定义scheme的POST请求默认会丢弃请求体内容,不管请求体是普通表单、JSON还是FormData格式,都会出现HTTPBody、HTTPBodyStream为nil的情况。
可用解决方案

方案1:JS侧透传序列化后的FormData内容

  • JS端发送携带FormData的XHR前,先将FormData序列化为可传输的字符串格式(二进制文件可先转base64编码),存入自定义请求头,比如X-Custom-Form-Data,同时把对应的Content-Type值也存入X-Custom-Content-Type自定义头。
  • WKURLSchemeHandler侧从WKURLSchemeTask.request.allHTTPHeaderFields中取出上述自定义头的内容,自行解析组装即可得到完整的FormData数据。

该方案无系统版本适配风险,兼容性最好,适合FormData体积不大的场景。

方案2:Hook WKWebView请求逻辑强制保留请求体

  • 可以通过Runtime交换NSURLRequest的HTTPBody方法,主动读取HTTPBodyStream的内容补全请求体,核心实现代码如下:
#import <objc/runtime.h>

@implementation NSURLRequest (FormDataFix)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class targetCls = NSClassFromString(@"WKNSURLRequest");
        if (!targetCls) return;
        SEL originalSel = @selector(HTTPBody);
        SEL swizzledSel = @selector(custom_getHTTPBody);
        Method originalMethod = class_getInstanceMethod(targetCls, originalSel);
        Method swizzledMethod = class_getInstanceMethod(self, swizzledSel);
        if (originalMethod && swizzledMethod) {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

- (NSData *)custom_getHTTPBody {
    NSData *originalBody = [self custom_getHTTPBody];
    if (originalBody) return originalBody;
    // 从HTTPBodyStream读取内容
    NSInputStream *stream = self.HTTPBodyStream;
    if (!stream) return nil;
    NSMutableData *bodyData = [NSMutableData data];
    uint8_t buffer[1024 * 4];
    NSInteger readLength;
    [stream open];
    while ((readLength = [stream read:buffer maxLength:sizeof(buffer)]) > 0) {
        [bodyData appendBytes:buffer length:readLength];
    }
    [stream close];
    return bodyData;
}
@end

该方案依赖WebKit内部私有类结构,iOS系统大版本升级可能出现兼容性问题,需要做好验证适配。

方案3:使用HTTP/HTTPS作为拦截scheme

  • 如果你的业务不需要完全自定义非标准scheme,可以直接用WKURLSchemeHandler注册http/https scheme做请求拦截,这种场景下WebKit不会默认丢弃POST请求体,你可以直接从WKURLSchemeTask.request中拿到完整的FormData内容。

内容的提问来源于stack exchange,提问作者Silin Vasya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:21:00