React Native对接Laravel上传PDF报422错误,求排查方案
React Native + Laravel PDF上传422错误排查与解决
问题分析
422状态码表示请求参数验证失败,结合你的代码,问题主要集中在前端FormData构造和请求头设置上,以下是具体解决步骤:
解决方法
- 修正FormData文件构造
Expo DocumentPicker返回的完整对象不能直接append到FormData,需要提取uri、name、type字段构造符合表单要求的文件对象:
// 修改pickDocument方法 const pickDocument = async () => { try { const result = await DocumentPicker.getDocumentAsync({ type: 'application/pdf', }); if (result.type === 'success') { const file = result.assets[0]; // 构造符合FormData规范的文件对象 setSelectedFile({ uri: file.uri, name: file.name, type: 'application/pdf' }); } } catch (error) { console.error('Error picking document: ', error); } };
- 移除手动设置的Content-Type
axios会自动为FormData请求生成包含boundary的multipart/form-data请求头,手动设置会丢失boundary参数,导致Laravel无法正确解析表单数据,删除请求中的headers配置:
const response = await axiosConfig.post('/upload-pdf', formData);
- 验证规则匹配检查
确认Laravel验证规则中的字段名pdf_file与前端append的字段名完全一致,同时确保上传文件为PDF格式且大小不超过10MB。
详细错误信息查看位置
- 前端:在catch块中打印
error.response.data,可直接获取Laravel返回的具体验证错误详情:
catch (error) { console.error('详细错误信息:', error.response?.data); }
- Laravel后端:日志文件位于项目根目录下的
storage/logs/laravel.log,里面会记录所有请求的验证错误、异常信息,直接查看即可定位问题。
完整代码
React Native前端代码
import React, { useState, useContext } from 'react'; import { View, Button, Text } from 'react-native'; import * as DocumentPicker from 'expo-document-picker'; import { AuthContext } from '../context/AuthProvider'; import axiosConfig from '../helpers/axiosConfig'; const UploadPDFScreen = () => { const [selectedFile, setSelectedFile] = useState(null); const { user } = useContext(AuthContext); const pickDocument = async () => { try { const result = await DocumentPicker.getDocumentAsync({ type: 'application/pdf', }); if (result.type === 'success') { const file = result.assets[0]; setSelectedFile({ uri: file.uri, name: file.name, type: 'application/pdf' }); } } catch (error) { console.error('Error picking document: ', error); } }; const uploadFile = async () => { if (!selectedFile) { console.error('No file selected'); return; } try { const formData = new FormData(); formData.append('pdf_file', selectedFile); axiosConfig.defaults.headers.common['Authorization'] = 'Bearer ' + user.token; const response = await axiosConfig.post('/upload-pdf', formData); console.log('Upload success:', response.data); } catch (error) { console.error('Error uploading file:', error); console.error('详细错误信息:', error.response?.data); } }; return ( <View> <Button title="Select PDF File" onPress={pickDocument} /> <Button title="Upload File" onPress={uploadFile} disabled={!selectedFile} /> {selectedFile && ( <View> <Text>Selected PDF: {selectedFile.name}</Text> </View> )} </View> ); }; export default UploadPDFScreen;
Laravel后端代码
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Validator; class FileUploadController extends Controller { /** * Handle the upload of a PDF file. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function uploadPdf(Request $request) { // Define the validation rules $validator = Validator::make($request->all(), [ 'pdf_file' => 'required|file|mimes:pdf|max:10240', // max size 10MB ]); // Check if the validation fails if ($validator->fails()) { return response()->json(['error' => $validator->errors()], 422); } // Retrieve the validated file $file = $request->file('pdf_file'); // Store the file in the specified directory $filePath = $file->store('public/pdfs'); // Return a successful response with the file path return response()->json([ 'file_path' => Storage::url($filePath), 'message' => 'File uploaded successfully', ], 201); } }
内容的提问来源于stack exchange,提问作者Ahmed Habeeb
相关产品推荐
相关产品推荐

