[英]How to send files to Django REST Framework from React?
I need to send arbitrary (eg xls
) files from React-based frontend to Django REST Framework backend.我需要将任意(例如xls
)文件从基于 React 的前端发送到 Django REST Framework 后端。
Googled and tried many code variants for couple of hours, none of them worked completely.谷歌搜索并尝试了几个小时的许多代码变体,但没有一个完全有效。
Here are essential parts of code:以下是代码的重要部分:
1.1 Form input field 1.1 表单输入字段
<input
type="file"
multiple={true}
accept=".xls,.xlsx,.csv,.txt"
onChange={this.handleFilesChosen}
/>
1.2 handleFilesChosen 1.2 handleFilesChosen
handleFilesChosen = event => {
this.setState({
files: event.target.files
});
}
1.3 Upload click handler ( authHeader
is function substituting Authorization Bearer token) 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)
I selected simple txt file (to make debugging easy, binary will go later) with hello world
content, uploaded it and get <QueryDict: {}>
in Django runserver
console.我选择了简单的txt文件(使调试容易,双星将在稍后去)与hello world
内容,上传,并得到<QueryDict: {}>
在Django runserver
控制台。
If I look at Chrome network tab, I see following empty request payload instead of real file content:如果我查看 Chrome 网络选项卡,我会看到以下空请求负载而不是实际文件内容:
------WebKitFormBoundaryYw6ABRFkvxatzHqi
Content-Disposition: form-data; name="files"; filename="foo.txt"
Content-Type: text/plain
------WebKitFormBoundaryYw6ABRFkvxatzHqi--
Tried to remove contentType
header - got 400 error with message JSON parse error
(browser substitutes JSON contentType header automatically).试图删除contentType
标头 - 出现 400 错误,消息JSON parse error
(浏览器自动替换 JSON contentType 标头)。
I'm stuck.我被困住了。 Could anybody guide me?有人可以指导我吗?
Found solution.找到解决方案。 I should not set Content-Type
header manually, it is set automatically with boundary
option.我不应该手动设置Content-Type
标头,它是使用boundary
选项自动设置的。 Now Django's request.FILES
work too and I could work with uploaded files from backend using code like:现在 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()
...
I decided to maintain uniformity in the API and send the image within JSON.我决定在 API 中保持一致性并在 JSON 中发送图像。
In React:在反应中:
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>);
In Django (DRF):在 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.