我正在尝试上传多个文件,这是导师为学生上传的作业的一部分。然后学生就可以点击链接并将文件下载到他们的计算机上。
下面是上传文件时的表单:
import React, { useState, useContext } from "react";
import { UserContext } from "./App";
import { useLocation, useNavigate } from "react-router-dom";
import { Container, Form, Row, Col, Button } from "react-bootstrap";
function AssignWork() {
const [error, setError] = useState([]);
const location = useLocation();
const navigate = useNavigate();
const { studentId } = location.state;
const { currentUser, setStudents } = useContext(UserContext);
const [assignmentData, setAssignmentData] = useState({
name: "",
notes: "",
subject: "",
tutor_id: currentUser.id,
student_id: studentId,
files: "",
});
// const [files, setFiles] = useState(null);
function handleChange(e) {
setAssignmentData({ ...assignmentData, [e.target.name]: e.target.value });
}
function onFormSubmit(e) {
e.preventDefault();
// const formData = new FormData();
// for (let data in assignmentData) {
// formData.append(data, assignmentData[data]);
// }
fetch("/assignments", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(assignmentData),
}).then((resp) => {
if (resp.ok) {
resp.json().then((newAssignment) => {
console.log(newAssignment);
let studentsList = [
...new Map(
newAssignment.tutor.students.map((student) => [
student["id"],
student,
])
).values(),
];
setStudents(studentsList);
navigate("/students");
});
} else {
resp.json().then((error) => setError(error.errors));
}
});
}
return (
<Container
style={{
marginTop: "24px",
padding: "24px",
border: ".5px solid grey",
borderRadius: "8px",
width: "75%",
}}
>
<h2
style={{
border: ".5px solid grey",
marginBottom: "24px",
borderRadius: "8px",
padding: "8px",
}}
>
Assignment
</h2>
<Form onSubmit={onFormSubmit}>
<Row>
<Col>
<Form.Label>Name:</Form.Label>
<Form.Control
type='text'
name='name'
value={assignmentData.name}
onChange={handleChange}
/>
</Col>
<Col>
<Form.Label>Subject:</Form.Label>
<Form.Control
type='text'
name='subject'
value={assignmentData.subject}
onChange={handleChange}
/>
</Col>
</Row>
<Row style={{ marginTop: "16px" }}>
<Col>
<Form.Label>Notes:</Form.Label>
<Form.Control
as='textarea'
name='notes'
value={assignmentData.notes}
onChange={handleChange}
/>
</Col>
</Row>
<Row style={{ marginTop: "16px" }}>
<Col>
<Form.Control
type='file'
name='file'
multiple
onChange={(e) =>
setAssignmentData({ ...assignmentData, files: e.target.files })
}
/>
</Col>
</Row>
<Row
style={{
margin: "16px",
justifyContent: "center",
}}
>
<Button type='submit' variant='success' style={{ maxWidth: "33%" }}>
Upload
</Button>
</Row>
{/* {error.map((error) => {
return <p key={error}>{error}</p>;
})} */}
</Form>
</Container>
);
}
export default AssignWork;
我无法将文件正确发送到Rails后端。它要么在命中'byebug'之前抛出一个错误,要么命中byebug但params[:files]为nil。我还需要一种方法来呈现文件的URL时,将其发送回前端。文件的存储目前是通过ActiveStorage完成的,ActiveStorage为用户存储头像。
这是当前的后端代码,当我试图解决这个问题时,大部分都被注解掉了:
def create
byebug
# assignment = Assignment.create!(new_assignment_params)
# assignment.update({ files: params[:files] })
# render json: assignment, include: "tutor.students.assignments", status: :created
end
def destroy
assignment_to_delete = find_assignment
if assignment_to_delete.tutor_id == @current_user.id
assignment_to_delete.destroy
head :no_content
else
render json: { error: "You do not have permission to destroy this assignment." }, status: :unauthorized
end
end
private
def new_assignment_params
params.permit(:name, :subject, :notes, :tutor_id, :student_id, :files)
end
链接到repo:https://github.com/mykovasyl/tutor-plus.我正在运行Rails 6!
任何帮助是赞赏!!
1条答案
按热度按时间oyjwcjzk1#
您正在尝试在JSON请求中发送文件。那是行不通的您需要多部分表单请求来发送二进制格式的文件。要做到这一点,你需要
post
ing一个FormData对象,它将使用multipart/form-data
内容类型(当使用FormData
对象和fetch
时,这是自动设置的。您还可以通过将json作为FormData
上的属性来发送一些JSON文件。现在发送到服务器的不是JSON,而是多部分表单数据,看起来像这样。
提交的请求主体中的“部分”与文件一样多,另外还有一个JSON元数据的“data”键。
在服务器上还有更多的工作要做。您的服务器将需要解析多部分表单数据,并分别在
data
键上提取文件(我已经根据文件名键入了这些文件)和JSON。我不是很熟悉ruby on rails,但我认为它可以开箱即用。检查传入请求的参数。