如何上传IAP base64收据至服务器?长串收据上传后服务器收空值问题
问题根因
你现在遇到的“服务器接收为空”的情况,基本和base64字符串过长没关系,核心诱因通常是这几个:
- 没有给
URLRequest设置明确的Content-Type请求头,网关或服务端会直接忽略没有格式声明的POST请求体 - 你当前直接传raw JSON二进制流的写法,在传统PHP环境下,默认的
$_POST变量只会解析application/x-www-form-urlencoded格式的表单参数,根本不会读取raw流内容,自然取到空值 - 排除前两个问题后,才需要考虑服务端的请求体大小限制是否把内容截断了
适配性最好的上传实现方案
根据你的后端解析逻辑选对应方案即可,不用两种都改:
场景1:后端明确支持接收raw JSON(即通过php://input读取请求流)
只需要在现有代码基础上补全请求头即可,完全不用改其他逻辑:
// 在request配置阶段追加这行 request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
这个写法下,只要你的服务端POST body大小配置不低于8M(PHP默认post_max_size就是8M,完全可以装下长度通常在几K到几百K的IAP base64收据),就不会出现传输异常。
场景2:后端是默认PHP配置,直接通过$_POST取参数
这时候别硬发raw JSON了,改成标准表单格式提交,是对旧服务兼容性最高的写法:
let url = URL(string: "https://ios.jobyme88.com/KidsLearnHindi/save-shopping.php")! var request = URLRequest(url: url) request.httpMethod = "POST" // 构造表单参数,把你需要提交的base64收据和其他业务参数存在字典里 let paramDict: [String: String] = [ "receipt_data": yourBase64Receipt, // 替换成你的收据字符串 "product_id": "对应的内购商品ID" ] // 拼接表单格式的请求体,注意对base64做特殊字符转义 let bodyString = paramDict.map { key, value in let encodedValue = value .addingPercentEncoding(withAllowedCharacters: .alphanumerics)! .replacingOccurrences(of: "+", with: "%2B") .replacingOccurrences(of: "/", with: "%2F") .replacingOccurrences(of: "=", with: "%3D") return "\(key)=\(encodedValue)" }.joined(separator: "&") request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type") request.httpBody = bodyString.data(using: .utf8)
注意:别直接用默认的.urlQueryAllowed给base64编码,这个规则会把base64里的+识别为空格、把/识别为路径分隔符,传到后端的内容就会变成无效字符串,单独对这几个base64里的特殊字符做百分号编码才是稳妥的。
容易踩的额外排查点
- 绝对不要把超长的base64收据拼在URL的查询参数里,绝大多数服务器对URL的长度限制是1K-4K,超长会直接被截断成空值,所有长文本参数必须放在POST请求体里
- 如果改完格式还是收不到内容,先在后端做原始请求日志:不要直接读
$_POST,用file_get_contents("php://input")把收到的原始内容长度打出来,就能快速定位是客户端没把内容传出来,还是服务端解析逻辑有问题,还是网关层做了大小截断 - 检查服务端配置:PHP的
post_max_size、Nginx的client_max_body_size如果被设置成小于几K的阈值,也会直接把超长请求体丢弃,导致后端拿到空值
内容的提问来源于stack exchange,提问作者Shark Deng
相关产品推荐
相关产品推荐

