[英]How to send CSRF Cookie from React to Django Rest Framework with Axios
[英]How to send files to Django REST Framework from React?
我需要将任意(例如xls
)文件从基于 React 的前端发送到 Django REST Framework 后端。
谷歌搜索并尝试了几个小时的许多代码变体,但没有一个完全有效。
以下是代码的重要部分:
1.1 表单输入字段
<input
type="file"
multiple={true}
accept=".xls,.xlsx,.csv,.txt"
onChange={this.handleFilesChosen}
/>
1.2 handleFilesChosen
handleFilesChosen = event => {
this.setState({
files: event.target.files
});
}
1.3 上传点击处理程序( authHeader
是代替 Authorization Bearer token 的函数)
handleUploadClick = event => {
let formData = new FormData();
for (let file of this.state.files) {
formData.append('files', file);
}
const csrf = this.getCookie('csrftoken');
fetch(`${API_BASE_PATH}/load-input-data/`, {
method: 'POST',
headers: authHeader({contentType: 'multipart/form-data', csrf: csrf}),
body: formData,
})
.then(result => result.json())
.catch(error => error);
}
class LoadInputDataView(APIView):
parser_class = (MultiPartParser,)
@method_decorator(login_required)
def post(self, request, format=None):
print(request.data)
return Response(status=status.HTTP_201_CREATED)
我选择了简单的txt文件(使调试容易,双星将在稍后去)与hello world
内容,上传,并得到<QueryDict: {}>
在Django runserver
控制台。
如果我查看 Chrome 网络选项卡,我会看到以下空请求负载而不是实际文件内容:
------WebKitFormBoundaryYw6ABRFkvxatzHqi
Content-Disposition: form-data; name="files"; filename="foo.txt"
Content-Type: text/plain
------WebKitFormBoundaryYw6ABRFkvxatzHqi--
试图删除contentType
标头 - 出现 400 错误,消息JSON parse error
(浏览器自动替换 JSON contentType 标头)。
我被困住了。 有人可以指导我吗?
找到解决方案。 我不应该手动设置Content-Type
标头,它是使用boundary
选项自动设置的。 现在 Django 的request.FILES
也可以工作了,我可以使用如下代码处理从后端上传的文件:
class ParseInputDataView(APIView):
parser_class = (MultiPartParser,)
permission_classes = [permissions.IsAuthenticated]
def post(self, request, controller_id, format=None):
for file_entry in request.FILES.getlist('files'):
uploaded_file_name = file_entry.name
uploaded_file_content = file_entry.read()
...
我决定在 API 中保持一致性并在 JSON 中发送图像。
在反应中:
const [image, setImage] = useState(null);
const handleImageChange = (e) => {
e.preventDefault();
const reader = new FileReader();
reader.onload = () => {
var blocks = reader.result.split(";");
const realData = blocks[1].split(",")[1];
setImage(realData);
};
reader.onerror = (error) => console.error(error);
reader.readAsDataURL(e.target.files[0]);
};
const onSaveHandler = () => {
fetch(`/url`, {
method: "post",
credentials: "include", // send cookie with auth
headers: {
"Content-Type": "application/json",
"X-CSRFToken": document.getElementById("csrf-token").value,
}
body: JSON.stringify({imageData: image}),
});
}
return(
<div>
<input
onChange={handleImageChange}
id="logo"
type="file"
multiple="false"
accept="image/*"
/>
<button onClick={onSaveHandler}>
SAVE
</button>
</div>);
在 Django (DRF) 中:
class CustomerViewSet(viewsets.ModelViewSet):
# override create method
def create(self, request, *args, **kwargs):
image_path = "whatever.jpg"
print('save image on disk: ' + image_path)
with open(image_path, "wb") as fh:
fh.write(base64.b64decode(request.data.get("imageData")))
return super().create(request)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.