[英]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.