我有一个 React Redux 应用程序和一个 Django 服务器。我的 django 服务器有一个端点,我可以从 s3 中提取文件,并对文件进行 Base64 编码并返回编码后的字符串。当我的 redux fetch 操作完成时,我想下载文件,而无需导航到我的 React 应用程序中的新页面。这是代码:
// DocumentReducer.tsx (+ all necessary imports)
export const getDocument = createAsyncThunk("document/download", async (payload: any) => {
const {id} = payload
const response = await instance.get(`tables/document/download/${id}`)
return response.data
})
const documentSlice = createSlice({
name: "document",
initialState: initialState,
reducers:{},
extraReducers: (builder) => {
...
builder.addCase(getDocument.fulfilled, (state, action) => {
const file = action.payload.file
window.location.href = 'data:application/octet-stream;base64,' + file
state.status = 'fulfilled'
})
}
})
// ExportComponent.tsx (+ all necessary imports)
export const ExportButton: React.FC<ExportButtonProps> = ({document_id}) => {
const dispatch = useAppDispatch()
const handleClick = () => {
const payload = {id: document_id}
dispatch(getDocument(payload))
}
return (
<Button variant="contained" size="small" onClick={handleClick}>
<div className="flex gap-3">
<p>Export</p>
<ArrowDownTrayIcon className='w-4 text-white'/>
</div>
</Button>
)
}
在服务器端:
# views.py
def encode_document(s3_key):
""" get document from s3 and base 64 encode the document """
buffer = BytesIO()
output_stream = BytesIO()
S3_CLIENT.download_fileobj("BUCKET_NAME", s3_key, buffer)
encoded = b64encode(buffer.getvalue()).decode()
return encoded
class DocumentS3(APIView):
parser_classes = [JSONParser]
permission_classes = [IsAuthenticated]
def get(self, request, document_id):
document = Document.objects.get(id=document_id)
encoded = encode_document(document.s3_key)
print(encoded[:10])
return Response({"file": encoded}, status=status.HTTP_200_OK)
我的服务器成功返回必要的编码字节。下载链接将我带到未找到的页面。有谁知道如何在 redux 中使这个导航成功?
不要在单页应用程序中执行
window.location.href =
- 常见的解决方案例如是这个答案:如何在React js中下载文件 - 一个限制是,如果我记得的话,下载需要由用户操作启动正确地(例如单击按钮),您不能在后台突然开始下载。
问题并非特定于 React 或 Redux 顺便说一句,当以编程方式启动下载时,任何单页应用程序都会遇到相同的问题。