在Postman客户端中操作成功完成。我收到响应并且文件已成功更新,但是问题出现在reactjs v18.2.0 react-redux v8.0.5
以下是我使用mutation发出post请求时得到的响应=>
{
"message": "The file field is required.",
"errors": {
"file": [
"The file field is required."
]
}
}
以下为api路由
// upload file
Route::post('/document/upload-file', [DocumentController::class, 'uploadDocumentFile']);
DocumentController 的操作
// upload file and return file url
public function uploadDocumentFile(Request $request)
{
$this->validate($request, [
'file' => 'required|file|mimes:jpg,png,pdf|max:2048',
]);
$file = $request->file('file');
$fileUrl = $file->store('uploads/documents', 'public');
return response()->json(['file_url' => $fileUrl]);
}
帖子请求=>
const [title, setTitle] = useState<string>("");
const [body, setBody] = useState<string>("");
const [file, setFile] = useState<File | "">("");
const [uploadFile] = useUploadFileMutation();
const handleFileUpload = async (submittedFile: File) => {
try {
const formData = new FormData();
formData.append("file", submittedFile);
const token = localStorage.getItem("token");
const response: any = await uploadFile(formData).unwrap();
// Check if the file_url is present in the response
const fileUrl = response;
if (fileUrl) {
console.log("File Url:", fileUrl);
} else {
console.error("File URL not found in the response.");
}
} catch (error) {
// Handle errors
console.error("Error uploading file:", (error as Error).message);
}
};
const handleSubmit = async (e: React.FormEvent<HTMLElement>) => {
e.preventDefault();
if (file !== "") {
console.log("File found ! Preparing the upload...");
await handleFileUpload(file);
}
};
从 ui 获取文件的表单
<form onSubmit={handleSubmit}>
<div className="grid grid-cols-1 gap-5">
<div>
<label htmlFor="document-title"> Title </label>
<FormInput type="text" name="title" id="document-title" value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</div>
<div>
<label htmlFor="document-body"> Description </label>
<FormInput type="textarea" name="answer" id="document-body" value={body}
onChange={(e) => {
setBody(e.target.value);
}} />
<div className="max-w-xl my-6">
<Dropzone onDrop={(acceptedFiles) => setFile(acceptedFiles[0])}>
{({ getRootProps, getInputProps }) => (
<section>
<div
{...getRootProps()}
className="w-full h-full relative"
>
<input
type="file"
name="file"
{...getInputProps()}
/>
<p className="absolute left-[20%] top-[43%]">
Drag 'n' drop some files here, or click to select
files
</p>
</div>
</section>
)}
</Dropzone>
</div>
</div>
<div>
<button
type="submit"
>
Submit
</button>
</div>
</div>
</form>
RTK 突变请求:
uploadFile: builder.mutation({
query: (body) => ({
url: `/document/upload-file`,
method: "POST",
formData: true,
body,
}),
}),
ApiSlice
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/dist/query/react";
// create api slice
export const apiSlice = createApi({
reducerPath: "api",
baseQuery: fetchBaseQuery({
baseUrl: `https://example_server.com/api`,
prepareHeaders: (headers) => {
headers.set("X-Requested-With", "XMLHttpRequest");
headers.set("Content-Type", "application/json");
headers.set("Accept", "application/json");
const token = localStorage.getItem("token");
if (token) {
headers.set("Authorization", `Bearer ${token}`);
}
return headers;
},
}),
endpoints: (builder) => ({}),
});
<?php
namespace App\Http\Controllers;
use App\Models\Document;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class DocumentController extends Controller
{
public function getAllDocuments()
{
$documents = Document::all();
return response()->json($documents);
}
// public function show($id)
// {
// $document = Document::find($id);
// return response()->json($document);
// }
public function storeDocuments(Request $request)
{
$this->validate($request, [
'user_id' => 'required|exists:users,id',
'files_title' => 'required|string',
'files_description' => 'required|string',
'file' => 'required|file|mimes:jpg,png,pdf|max:2048',
]);
// Handle file upload and store it in the storage/uploads directory.
$file = $request->file('file');
$fileUrl = $file->store('uploads', 'public');
// Create the document with the validated data and file URL.
$document = Document::create([
'user_id' => $request->user_id,
'title' => $request->files_title,
'body' => $request->files_description,
'file_url' => $fileUrl,
'position' => $request->position ?? 0,
]);
return response()->json($document, 201);
}
public function updateDocuments(Request $request, $id)
{
$this->validate($request, [
'user_id' => 'required|exists:users,id',
'files_title' => 'required|string',
'files_description' => 'required|string',
'file' => 'sometimes|file|mimes:jpg,png,pdf|max:2048', // Optional file update.
]);
$document = Document::findOrFail($id);
// If a new file is provided, update it and delete the old file.
if ($request->hasFile('file')) {
$newFile = $request->file('file');
$newFileUrl = $newFile->store('uploads', 'public');
// Delete the old file.
Storage::disk('public')->delete($document->file_url);
$document->update([
'user_id' => $request->user_id,
'title' => $request->files_title,
'body' => $request->files_description,
'file_url' => $newFileUrl,
'position' => $request->position ?? 0,
]);
} else {
// No new file provided, update the document with existing file.
$document->update([
'user_id' => $request->user_id,
'title' => $request->files_title,
'body' => $request->files_description,
'position' => $request->position ?? 0,
]);
}
return response()->json($document);
}
public function destroyDocuments($id)
{
$document = Document::find($id);
if (!$document) {
return response()->json(['message' => 'Document not found'], 404);
}
// Delete the associated file from the 'uploads' directory in the 'public' disk.
Storage::disk('public')->delete($document->file_url);
// Delete the document from the database.
$document->delete();
return response()->json(['message' => 'Document deleted']);
}
public function updatePosition(Request $request)
{
$this->validate($request, [
'documents' => 'required|array',
'position' => 'required|integer',
]);
$documents = $request->documents;
foreach ($documents as $document) {
Document::where('id', $document['id'])->update(['position' => $document['position']]);
}
return response()->json(['message' => 'Position updated!']);
}
// upload file and return file url
public function uploadDocumentFile(Request $request)
{
$this->validate($request, [
'file' => 'required|file|mimes:jpg,png,pdf|max:2048',
]);
$file = $request->file('file');
$fileUrl = $file->store('uploads/documents', 'public');
return response()->json(['file_url' => $fileUrl]);
}
}
我正在尝试上传文件。 期望返回文件路径
添加标头 'Skip-Content-Type': true,并删除 'formData' 参数对我的情况有帮助
示例:
uploadFile: builder.mutation({
query: (body) => ({
url: `/document/upload-file`,
headers: {
'Skip-Content-Type': true
},
method: "POST"
body,
}),
}),