React Native:无法在“FormData”上执行“附加”:参数 2 不是“Blob”类型。在新的 ApolloError
Posted
技术标签:
【中文标题】React Native:无法在“FormData”上执行“附加”:参数 2 不是“Blob”类型。在新的 ApolloError【英文标题】:React Native: Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'. at new ApolloError 【发布时间】:2020-07-24 02:05:56 【问题描述】:我正在尝试通过使用带有 createUploadLink() 的 Apollo 客户端将图像从我的 react 本机应用程序上传到 graphql。当我试图通过将 ReactNativeFile 作为变量传递来改变数据时,它会说
"network request failed: Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'. at new ApolloError ".
这是我正在尝试使用的突变
mutation publishPost(
$content: String!
$LocationInput: LocationInput!
$InputPostAttachment: [InputPostAttachment!]
)
publishPost(
content: $content
location: $LocationInput
attachments: $InputPostAttachment
)
content
InputPostAttachment 有类型
type InputPostAttachment
type: PostAttachmentType!
file: Upload!
Apollo 客户端设置,我正在使用 apollo-upload-client
const httpLink = createUploadLink(
uri: 'http://localhost:8000/graphql',
);
const authLink = setContext(async (headers: any) =>
const token = await getToken();
return
...headers,
headers:
authorization: token ? `Bearer $token` : null,
,
;
);
const link = authLink.concat(httpLink);
// create an inmemory cache instance for caching graphql data
const cache = new InMemoryCache();
// instantiate apollo client with apollo link instance and cache instance
export const client = new ApolloClient(
link,
cache,
);
文件上传功能,我正在使用 react-native-image-crop-picker 进行多图像选择
const [image, setimage] = useState([]);
const _pickImage = () =>
ImagePicker.openPicker(
includeBase64: true,
multiple: true,
).then((images: any) =>
let imageData: any = [];
images.map((data: any) =>
const file = new ReactNativeFile(
uri: data.path,
name: data.filename,
type: data.mime,
);
imageData.push(
type: 'IMAGE',
file: file,
);
);
setimage(imageData);
console.log(images);
);
;
const handlePost = async () =>
const InputPostAttachment: any = [...image];
const LocationInput =
place: place,
vicinity: vicinity,
province: province,
;
publishPost(variables: content, LocationInput, InputPostAttachment)
.then((data) =>
console.log(data);
props.navigation.navigate('Home');
)
.catch((err) =>
console.log('err happened');
console.log(err);
);
;
有人可以帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:我的 apollo-client 是使用 apollo-boost 配置的,而我使用 chrome 调试器拦截网络导致了这个问题。
更具体地说,我使用以下代码在 chrome 调试器中获取我的应用发送的网络请求
global.XMLHttpRequest =
global.originalXMLHttpRequest || global.XMLHttpRequest;
global.FormData = global.originalFormData || global.FormData;
if (window.FETCH_SUPPORT)
window.FETCH_SUPPORT.blob = false;
else
global.Blob = global.originalBlob || global.Blob;
global.FileReader = global.originalFileReader || global.FileReader;
如果我们使用 chrome 调试器,apollo-upload-client 不会以多部分数据的形式发送数据。我们将面临网络问题。这个issue 有答案。或者我没有删除 apollo-boost 并且我的应用程序的某些部分正在使用它,这也是一个问题。
【讨论】:
【参考方案2】:除了chrome调试器问题,expo web上也会出现这个错误。
对于任何在 expo web(或 react-native web)上上传图片的人,这里有一个可行的解决方案:
/** Load image from camera/roll. */
const result = await ImagePicker.launchImageLibraryAsync(
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
quality: 1,
);
if (result.cancelled)
return;
/** web platform: blob. */
const convertBase64ToBlob = async (base64) =>
const response = await fetch(base64);
const blob = await response.blob();
return blob;
;
/** android/ios platform: ReactNativeFile.*/
const createReactNativeFile = (uri) =>
const file = new ReactNativeFile(
uri,
type: mime.lookup(uri) || 'image',
name: `file-$Date.now()`,
);
return file;
;
/** Use blob for web, ReactNativeFile otherwise. */
const file = Platform.OS === 'web'
? await convertBase64ToBlob(result.uri)
: createReactNativeFile(result.uri);
/** Upload image with apollo. */
mutate( variables: file );
在网络平台上,ImagePicker 返回一个 base64 值而不是文件路径。如果平台是 Android 或 iOS,则不会发生此问题,因为 ImagePicker 返回一个文件路径,这是 apollo-upload-client 所期望的。
解决方案是检测 URI 是否为 base64(当平台为“web”时会发生这种情况)并将其转换为 blob。
【讨论】:
以上是关于React Native:无法在“FormData”上执行“附加”:参数 2 不是“Blob”类型。在新的 ApolloError的主要内容,如果未能解决你的问题,请参考以下文章
将 react-native-signaturepad 输出转换为 formData?
FormData发送字符串值而不是react-native中的视频文件
关于React Native使用formData形式上传文件失败,请求失败报错:Net Error问题