PHP/Apache中RESTful PUT传输大JSON数据的替代方案咨询
嘿,我完全懂你现在的困扰——共享虚拟主机的配置限制真的能把人卡得没脾气,尤其是想在RESTful PUT请求里传大JSON数据的时候。结合你的情况,我整理了几个可行的替代方案,你可以根据自己的场景选:
1. 直接用PUT传输原始JSON(最推荐)
你之前用parse_str(file_get_contents("php://input"),$post_vars);没成功,是因为parse_str是用来解析URL编码的表单数据的,不是JSON格式。其实PUT请求本身就支持直接发送原始JSON,而且不受post_max_size限制(这个参数只针对POST的表单数据)。
PHP端正确的处理代码应该是这样:
// 读取PUT请求的原始请求体 $rawJson = file_get_contents('php://input'); // 解析成数组或对象 $parsedData = json_decode($rawJson, true); // 检查解析是否成功 if (json_last_error() === JSON_ERROR_NONE) { // 这里处理你的业务逻辑 var_dump($parsedData); } else { // 处理JSON解析错误 http_response_code(400); echo "Invalid JSON data"; }
前端发送的时候,只需要设置请求头Content-Type: application/json,然后把JSON字符串直接作为请求体发送就行,完全不用multipart那套。
2. 把JSON当二进制文件用PUT传输
如果上面的方案因为主机的其他限制(比如输入流大小限制)行不通,你可以把JSON打包成一个临时文件(比如命名为data.json),然后用PUT请求直接发送文件内容。
PHP端的处理和上面几乎一样,还是读取php://input的内容,直接解析或者保存到文件:
$fileContent = file_get_contents('php://input'); // 直接解析JSON $data = json_decode($fileContent, true); // 或者先保存到临时文件再处理 // file_put_contents('/tmp/uploaded_data.json', $fileContent);
前端发送时设置Content-Type: application/octet-stream,把文件内容作为请求体发送即可,不需要multipart。
3. 分块传输超大规模JSON
如果你的JSON数据大到单次传输都可能超时或者被拦截,可以考虑分块传输:
- 前端把完整JSON拆分成多个小块,每个请求带上块序号、总块数的标识
- 服务器端接收每一块后,保存到临时文件或者数据库中
- 所有块接收完成后,再拼接成完整的JSON进行解析
这个方案需要额外处理分块的完整性和顺序,稍微复杂,但适合GB级别的超大数据。
4. 用POST伪装PUT+multipart文件上传(妥协方案)
如果你的业务必须要类似文件上传的方式,又绕不开主机的post_max_size限制,可以用POST请求伪装PUT语义(很多PHP框架都支持这种方式):
- 前端发送POST请求,表单里包含一个文件字段(把JSON作为文件上传),同时加上
_method=PUT的参数 - 服务器端先判断请求方法,再处理文件上传
PHP端示例代码:
// 处理HTTP方法伪装 $requestMethod = $_SERVER['REQUEST_METHOD']; if ($requestMethod === 'POST' && isset($_POST['_method'])) { $requestMethod = strtoupper($_POST['_method']); } if ($requestMethod === 'PUT') { // 检查是否有上传的JSON文件 if (isset($_FILES['json_upload'])) { $tmpFilePath = $_FILES['json_upload']['tmp_name']; $jsonData = file_get_contents($tmpFilePath); $parsedData = json_decode($jsonData, true); // 处理业务逻辑 } else { http_response_code(400); echo "No JSON file uploaded"; } }
这种方式利用了upload_max_filesize参数(通常比post_max_size宽松,甚至可以联系主机商调整这个参数),绕过POST的表单大小限制,同时还能保持RESTful的语义。
内容的提问来源于stack exchange,提问作者user2526586

