React Native中通过RTK Query获取PDF文件失败求助
解决RTK Query获取PDF时的JSON解析错误
问题原因
RTK Query 默认会尝试将响应解析为 JSON,即便你设置了 responseType: 'blob',若配置不当,它仍会触发JSON解析逻辑,导致PDF二进制数据被当作JSON解析,抛出Unexpected token: %错误(PDF文件开头通常是%PDF-)。
修复方案
1. 正确配置Query的responseType与transformResponse
在你的CourseApi中,需确保两点:
- 在
query配置里设置responseType: 'blob',明确告知RTK Query以Blob格式接收响应 - 移除
transformResponse里的response.blob()调用——当responseType设为blob时,响应本身已经是Blob对象,无需再次转换;若需自定义处理,直接返回该Blob即可
示例代码:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const courseApi = createApi({ reducerPath: 'courseApi', baseQuery: fetchBaseQuery({ baseUrl: '你的API基础地址' }), endpoints: (builder) => ({ getTranscript: builder.query<Blob, string>({ query: (courseId) => ({ url: `/courses/${courseId}/transcript`, responseType: 'blob', // 关键配置:指定响应类型为blob }), // 直接返回Blob,无需额外转换 transformResponse: (response: Blob) => response, }), }), }); export const { useGetTranscriptQuery } = courseApi;
2. 确认API响应的Content-Type
确保后端返回的响应头Content-Type确实为application/pdf,RTK Query会结合这个响应头与responseType配置正确处理响应,避免解析错误。
3. 调用Query后的PDF处理示例
在组件中获取到Blob对象后,可通过React Native生态库(如expo-file-system或react-native-fs)实现下载/预览逻辑:
import { useGetTranscriptQuery } from './courseApi'; import * as FileSystem from 'expo-file-system'; import { Button } from 'react-native'; const TranscriptDownloadButton = ({ courseId }) => { const { data: transcriptBlob, isLoading } = useGetTranscriptQuery(courseId); const handleDownload = async () => { if (!transcriptBlob) return; // 将Blob转为Base64后写入本地文件 const base64Data = await new Promise((resolve) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result?.split(',')[1]); reader.readAsDataURL(transcriptBlob); }); const fileUri = `${FileSystem.documentDirectory}transcript.pdf`; await FileSystem.writeAsStringAsync(fileUri, base64Data, { encoding: FileSystem.EncodingType.Base64 }); // 可在此处添加打开文件的逻辑 }; return ( <Button title={isLoading ? '加载中...' : '下载成绩单'} onPress={handleDownload} disabled={isLoading || !transcriptBlob} /> ); };
关键注意点
- 不要在
transformResponse中调用response.blob():当responseType设为blob时,response已经是Blob实例,response.blob()会返回Promise,RTK Query同步处理时会将这个Promise当作普通值,引发后续解析错误。 - 若需异步处理响应,
transformResponse可返回Promise,但要确保后续逻辑能正确处理异步结果;对于Blob获取场景,通常无需额外异步操作。
内容的提问来源于stack exchange,提问作者Rabia Shahzad
相关产品推荐
相关产品推荐

