使用 Google 选择器 API 后尝试下载文件时出现错误 401
Error 401 when trying to download a file after using Google Picker API
我有一个 React 应用程序,它允许用户输入特定的 Google 文档,然后我们分析其中的内容。对于第 1 步,选择文档,我使用 this nifty npm package,这对我来说也是一个“OAuth 令牌”,我认为它是一个 access_token
,我可以用它来制作 API来电。我将返回的令牌和 Picker API 返回的数据设置为组件中的状态变量,如下所示
<GooglePicker clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
developerKey={process.env.REACT_APP_GOOGLE_API_KEY}
scope={SCOPES}
onAuthenticate={(token: any) => {
setGoogleToken(token)
}}
onChange={(data: any) => {
setGoogleData(data);
nextOnboardingStage();
}}
onAuthFailed={(data: any) => console.log('on auth failed:', data)}
multiselect={true}
navHidden={true}
authImmediate={false}
mimeTypes={['application/vnd.google-apps.document']}
viewId={'DOCS'}>
<MyCustomButton />
</GooglePicker>
然后我尝试调用 Drive API export function 以在此函数中下载所述文件
const downloadGoogleDoc = async (authToken: string, fileID: string) => {
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `token ${authToken}`
}
});
console.log(res);
};
但是,我在执行此操作时遇到了 401 错误。有人可以指出我在哪里失去了授权吗?非常感谢
编辑我的整个组件在下面
const SCOPES = ['https://www.googleapis.com/auth/drive.readonly'];
const Project: React.FC<ProjectInput> = () => {
const [googleToken, setGoogleToken] = useState<string>();
const [googleData, setGoogleData] = useState<any>({});
const [documentData, setDocumentData] = useState();
const downloadGoogleDoc = async (authToken: string, fileID: string) => {
try {
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
console.log(res);
} catch(e) {
console.log(e);
console.log(e.message);
}
};
console.log(googleToken);
console.log(googleData);
const MyCustomButton = () => {
return (
<button className="mx-8 my-2 p-2 rounded bg-blue-500 text-white">
Select From Google Drive
</button>
)
}
if (googleToken && googleData.docs) {
downloadGoogleDoc(googleToken, googleData.docs[0].id);
}
return (
<div className={`ml-${sideBarWidth}`}>
<FadeIn>
<div className="flex flex-col min-h-screen bg-gray-500 py-6 justify-center sm:py-12">
<div className="py-3 sm:max-w-xl sm:mx-auto">
<div className="bg-white min-w-1xl flex flex-col rounded-xl shadow-lg">
<div className="flex">
<div>
<div>
<div className="px-8 py-5">
<h2 className="text-gray-800 text-3xl font-semibold">Great! Select the document you'd like us to scan</h2>
</div>
</div>
<GooglePicker clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
developerKey={process.env.REACT_APP_GOOGLE_API_KEY}
scope={SCOPES}
onAuthenticate={(token: any) => {
setGoogleToken(token)
}}
onChange={(data: any) => {
setGoogleData(data);
nextOnboardingStage();
}}
onAuthFailed={(data: any) => console.log('on auth failed:', data)}
multiselect={true}
navHidden={true}
authImmediate={false}
mimeTypes={['application/vnd.google-apps.document']}
viewId={'DOCS'}>
<MyCustomButton />
</GooglePicker>
</div>
</div>
</div>
</div>
</div>
</FadeIn>
</div>
);
};
export default Project;
编辑
正如@Tanaike 所说,我需要在我的请求中包含 MimeType,工作函数如下
const downloadGoogleDoc = async (authToken: string, fileID: string) => {
try {
const params = new URLSearchParams([['mimeType', 'text/html']]);
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
params,
headers: {
'Authorization': `Bearer ${authToken}`
}
});
console.log(res);
} catch(e) {
console.log(e);
console.log(e.message);
}
};
我相信你的目标和你的情况如下。
- 您想知道
401
错误的原因。
- 根据您的脚本,我认为您可能想要下载 Google 文档文件(文档、电子表格、幻灯片等)以外的文件。
- 因为下载Google文档文件时,端点不正确。在Drive API v3中使用“Files: export”方法时,需要使用
mimeType
导出。
- 但是从你的回复中,我了解到你想使用“文件:导出”的方法下载一个 Google Docs 文件。
- 您的访问令牌可用于从 Google 驱动器下载文件。
修改点:
当我看到你下面的脚本时,我注意到除了端点之外的一个修改点。
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `token ${authToken}`
}
});
- 在这种情况下,
token
是不正确的。请修改为Bearer
。我认为这是错误 401
. 的原因
当使用catch
时,可以检索错误信息。
如果下载二进制文件,则直接检索二进制数据。那时,当使用responseType: 'arrayBuffer'
和responseType: 'blob'
时,数据分别被检索为array buffer和blob。
当以上几点反映到你的脚本中,就会变成下面这样。
修改后的脚本:
从:
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `token ${authToken}`
}
});
到:
const mimeType = "###"; // Please set the mimeType.
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export?mimeType=${mimeType}`, {
// responseType: `arrayBuffer`, // or 'blob'
headers: {
'Authorization': `Bearer ${authToken}`
}
}).catch(err => console.log(err.response));
console.log(res); // or res.data
注:
在此修改后的脚本中,假设您的访问令牌可用于从 Google 驱动器下载文件。所以请注意这一点。
当您使用“文件:导出”方式时,请使用Google Docs文件作为文件ID。请注意这一点。 Ref
参考文献:
我有一个 React 应用程序,它允许用户输入特定的 Google 文档,然后我们分析其中的内容。对于第 1 步,选择文档,我使用 this nifty npm package,这对我来说也是一个“OAuth 令牌”,我认为它是一个 access_token
,我可以用它来制作 API来电。我将返回的令牌和 Picker API 返回的数据设置为组件中的状态变量,如下所示
<GooglePicker clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
developerKey={process.env.REACT_APP_GOOGLE_API_KEY}
scope={SCOPES}
onAuthenticate={(token: any) => {
setGoogleToken(token)
}}
onChange={(data: any) => {
setGoogleData(data);
nextOnboardingStage();
}}
onAuthFailed={(data: any) => console.log('on auth failed:', data)}
multiselect={true}
navHidden={true}
authImmediate={false}
mimeTypes={['application/vnd.google-apps.document']}
viewId={'DOCS'}>
<MyCustomButton />
</GooglePicker>
然后我尝试调用 Drive API export function 以在此函数中下载所述文件
const downloadGoogleDoc = async (authToken: string, fileID: string) => {
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `token ${authToken}`
}
});
console.log(res);
};
但是,我在执行此操作时遇到了 401 错误。有人可以指出我在哪里失去了授权吗?非常感谢
编辑我的整个组件在下面
const SCOPES = ['https://www.googleapis.com/auth/drive.readonly'];
const Project: React.FC<ProjectInput> = () => {
const [googleToken, setGoogleToken] = useState<string>();
const [googleData, setGoogleData] = useState<any>({});
const [documentData, setDocumentData] = useState();
const downloadGoogleDoc = async (authToken: string, fileID: string) => {
try {
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `Bearer ${authToken}`
}
});
console.log(res);
} catch(e) {
console.log(e);
console.log(e.message);
}
};
console.log(googleToken);
console.log(googleData);
const MyCustomButton = () => {
return (
<button className="mx-8 my-2 p-2 rounded bg-blue-500 text-white">
Select From Google Drive
</button>
)
}
if (googleToken && googleData.docs) {
downloadGoogleDoc(googleToken, googleData.docs[0].id);
}
return (
<div className={`ml-${sideBarWidth}`}>
<FadeIn>
<div className="flex flex-col min-h-screen bg-gray-500 py-6 justify-center sm:py-12">
<div className="py-3 sm:max-w-xl sm:mx-auto">
<div className="bg-white min-w-1xl flex flex-col rounded-xl shadow-lg">
<div className="flex">
<div>
<div>
<div className="px-8 py-5">
<h2 className="text-gray-800 text-3xl font-semibold">Great! Select the document you'd like us to scan</h2>
</div>
</div>
<GooglePicker clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
developerKey={process.env.REACT_APP_GOOGLE_API_KEY}
scope={SCOPES}
onAuthenticate={(token: any) => {
setGoogleToken(token)
}}
onChange={(data: any) => {
setGoogleData(data);
nextOnboardingStage();
}}
onAuthFailed={(data: any) => console.log('on auth failed:', data)}
multiselect={true}
navHidden={true}
authImmediate={false}
mimeTypes={['application/vnd.google-apps.document']}
viewId={'DOCS'}>
<MyCustomButton />
</GooglePicker>
</div>
</div>
</div>
</div>
</div>
</FadeIn>
</div>
);
};
export default Project;
编辑
正如@Tanaike 所说,我需要在我的请求中包含 MimeType,工作函数如下
const downloadGoogleDoc = async (authToken: string, fileID: string) => {
try {
const params = new URLSearchParams([['mimeType', 'text/html']]);
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
params,
headers: {
'Authorization': `Bearer ${authToken}`
}
});
console.log(res);
} catch(e) {
console.log(e);
console.log(e.message);
}
};
我相信你的目标和你的情况如下。
- 您想知道
401
错误的原因。 - 根据您的脚本,我认为您可能想要下载 Google 文档文件(文档、电子表格、幻灯片等)以外的文件。
- 因为下载Google文档文件时,端点不正确。在Drive API v3中使用“Files: export”方法时,需要使用
mimeType
导出。 - 但是从你的回复中,我了解到你想使用“文件:导出”的方法下载一个 Google Docs 文件。
- 因为下载Google文档文件时,端点不正确。在Drive API v3中使用“Files: export”方法时,需要使用
- 您的访问令牌可用于从 Google 驱动器下载文件。
修改点:
当我看到你下面的脚本时,我注意到除了端点之外的一个修改点。
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, { headers: { 'Authorization': `token ${authToken}` } });
- 在这种情况下,
token
是不正确的。请修改为Bearer
。我认为这是错误401
. 的原因
- 在这种情况下,
当使用
catch
时,可以检索错误信息。如果下载二进制文件,则直接检索二进制数据。那时,当使用
responseType: 'arrayBuffer'
和responseType: 'blob'
时,数据分别被检索为array buffer和blob。
当以上几点反映到你的脚本中,就会变成下面这样。
修改后的脚本:
从:const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export`, {
headers: {
'Authorization': `token ${authToken}`
}
});
到:
const mimeType = "###"; // Please set the mimeType.
const res = await axios.get(`https://www.googleapis.com/drive/v3/files/${fileID}/export?mimeType=${mimeType}`, {
// responseType: `arrayBuffer`, // or 'blob'
headers: {
'Authorization': `Bearer ${authToken}`
}
}).catch(err => console.log(err.response));
console.log(res); // or res.data
注:
在此修改后的脚本中,假设您的访问令牌可用于从 Google 驱动器下载文件。所以请注意这一点。
当您使用“文件:导出”方式时,请使用Google Docs文件作为文件ID。请注意这一点。 Ref