如何将Base64或Blob格式的PDF文件附加到Azure DevOps工作项?
问题描述
尝试将云端下载的Blob格式PDF附加到Azure DevOps工作项时失败,错误提示无法从本地获取该文件(实际文件为Blob而非本地文件)。目前附加文本文件可正常运行,当前使用的上传函数如下:

const convertBlobToBase64 = (blob: Blob): Promise<string> => { return new Promise((resolve, reject) => { const reader = new FileReader() reader.readAsDataURL(blob) reader.onloadend = () => { const base64data = reader.result?.toString().split(',')[1] resolve(base64data || '') } reader.onerror = reject }) } export const addPdfAttachmentToWorkItem = async ( workItemId: number, pat: string, organizationUrl: string, projectId: string, pdfBlob: Blob, fileName: string ) => { try { const encodedPat = btoa(`:${pat}`) const url = `${organizationUrl}/${projectId}/_apis/wit/attachments?api-version=6.0&fileName=${fileName}&uploadType=simple` const pdfBase64 = await convertBlobToBase64(pdfBlob) const attachRes = await axios({ method: 'POST', url, data: pdfBase64, headers: { Authorization: `Basic ${encodedPat}`, 'Content-Type': 'application/octet-stream', }, }) const witUrl = `${organizationUrl}/${projectId}/_apis/wit/workitems/${workItemId}?api-version=6.0` const workItemData = [ { op: 'add', path: `/relations/-`, value: { rel: 'AttachedFile', url: attachRes.data.url, attributes: { comment: `Attached work package report for WIT ${workItemId}`, }, }, }, ] const response = await axios.patch(witUrl, workItemData, { headers: { Authorization: `Basic ${encodedPat}`, 'Content-Type': 'application/json-patch+json', }, params: { $expand: 'all', }, }) return response.data } catch (error) { console.error('Error updating work item:', error) throw error } }
问题分析
当前代码将Blob转换为Base64字符串后上传,文本文件因编码简单可兼容,但PDF作为二进制文件,Base64转换过程中可能出现编码损耗,且Axios对Base64字符串作为application/octet-stream类型数据的处理逻辑,容易导致二进制数据传输不完整,触发服务端错误。
解决方案
直接上传Blob原始数据,跳过Base64转换步骤,确保二进制数据完整传输:
export const addPdfAttachmentToWorkItem = async ( workItemId: number, pat: string, organizationUrl: string, projectId: string, pdfBlob: Blob, fileName: string ) => { try { const encodedPat = btoa(`:${pat}`) const url = `${organizationUrl}/${projectId}/_apis/wit/attachments?api-version=6.0&fileName=${fileName}&uploadType=simple` // 直接发送Blob原始数据,无需Base64转换 const attachRes = await axios({ method: 'POST', url, data: pdfBlob, headers: { Authorization: `Basic ${encodedPat}`, 'Content-Type': 'application/octet-stream', // 明确指定数据长度,保证服务端正确接收 'Content-Length': pdfBlob.size.toString() }, // 阻止Axios默认序列化,保留Blob原始格式 transformRequest: [(data) => data] }) const witUrl = `${organizationUrl}/${projectId}/_apis/wit/workitems/${workItemId}?api-version=6.0` const workItemData = [ { op: 'add', path: `/relations/-`, value: { rel: 'AttachedFile', url: attachRes.data.url, attributes: { comment: `Attached work package report for WIT ${workItemId}`, }, }, }, ] const response = await axios.patch(witUrl, workItemData, { headers: { Authorization: `Basic ${encodedPat}`, 'Content-Type': 'application/json-patch+json', }, params: { $expand: 'all', }, }) return response.data } catch (error) { console.error('Error updating work item:', error) throw error } }
额外检查点
- 确认Blob的MIME类型为
application/pdf,若下载的Blob类型不正确,可重新构造Blob:const correctedPdfBlob = new Blob([pdfBlob], { type: 'application/pdf' }) - 验证PAT权限,确保拥有Work Item Write和Attachment Write权限。
内容的提问来源于stack exchange,提问作者Smart Solutions
相关产品推荐
相关产品推荐

