使用JS上传文档至Azure Blob Storage时遇400认证格式错误
问题:拖拽PDF上传Azure Blob Storage时返回400认证错误
我编写了一段HTML/JS代码,实现将PDF文件拖拽上传至Azure Blob Storage并预览PDF的功能,但调用上传接口时返回400错误,提示:
Authentication information is not given in the correct format. Check the value of Authorization header.
已检查Blob存储容器及账户权限,仍未找到问题所在,代码如下:
<!DOCTYPE html> <html> <head> <title>File Upload to Azure Blob Storage</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js"></script> </head> <body> <div class="header"> <span class="header-text">Document Request Analyzer</span> <div class="search-container"> <input type="text" class="search-bar" placeholder="Search for specific request..."> </div> </div> <div class="upload-container"> <!--<div class="upload-icon">📁</div>--> <div class="drop-area" id="dropArea"> <span>Drag and Drop<br>Document<br>Request</span> </div> <button id="uploadButton" class="btn">Extract Request</button> <canvas id="pdfPreviewCanvas" class="preview-canvas"></canvas> </div> <script> const dropArea = document.getElementById('dropArea'); const uploadButton = document.getElementById('uploadButton'); const pdfPreviewCanvas = document.getElementById('pdfPreviewCanvas'); const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = '.pdf'; fileInput.style.display = 'none'; document.body.appendChild(fileInput); dropArea.addEventListener('dragenter', (e) => { e.preventDefault(); dropArea.classList.add('hover'); }); dropArea.addEventListener('dragover', (e) => { e.preventDefault(); }); dropArea.addEventListener('dragleave', () => { dropArea.classList.remove('hover'); }); dropArea.addEventListener('drop', (e) => { e.preventDefault(); dropArea.classList.remove('hover'); const file = e.dataTransfer.files[0]; fileInput.files = e.dataTransfer.files; handleFileUpload(file); }); uploadButton.addEventListener('click', () => { const file = fileInput.files[0]; handleFileUpload(file); }); async function handleFileUpload(file) { if (!file) { console.error('No file selected.'); return; } const accountName = 'test'; const containerName = 'test1234'; const storageAccessKey = 'test'; const currentDate = new Date(); const expiryDate = new Date(currentDate); expiryDate.setMinutes(currentDate.getMinutes() + 5); const sasToken = 'testing'; const blobName = file.name; const uploadUrl = `https://${accountName}.blob.core.windows.net/${containerName}/${blobName}${sasToken}`; const headers = new Headers(); headers.append('x-ms-blob-type', 'GeneralPurposeV2'); headers.append('x-ms-date', new Date().toUTCString()); headers.append('Content-Length', 0); headers.append('x-ms-version', '2020-04-08'); headers.append('Authorization', sasToken); // const formData = new FormData(); // formData.append('file', file); const requestOptions = { method: 'PUT', headers: headers, body: file }; try { const response = await fetch(uploadUrl, requestOptions); if (response.ok) { console.log('File uploaded successfully'); } else { console.error('Error uploading file:', response.statusText); } } catch (error) { console.error('An error occurred:', error); } // Display uploaded PDF preview const pdfUrl = URL.createObjectURL(file); const loadingTask = pdfjsLib.getDocument(pdfUrl); try { const pdfDocument = await loadingTask.promise; const firstPage = await pdfDocument.getPage(1); const viewport = firstPage.getViewport({ scale: 1 }); pdfPreviewCanvas.width = viewport.width; pdfPreviewCanvas.height = viewport.height; const canvasContext = pdfPreviewCanvas.getContext('2d'); const renderContext = { canvasContext, viewport, }; await firstPage.render(renderContext).promise; pdfPreviewCanvas.style.display = 'block'; } catch (error) { console.error('Error rendering PDF:', error); pdfPreviewCanvas.style.display = 'none'; } } </script> </body> </html>
错误原因及修复方案
1. SAS Token使用方式错误
你同时在uploadUrl拼接SAS Token,又在Authorization头中重复添加,这是错误的。Azure Blob Storage的SAS认证仅需将Token拼在URL末尾,无需额外设置Authorization头。
2. x-ms-blob-type值错误
x-ms-blob-type的有效值为BlockBlob、PageBlob或AppendBlob,你设置的GeneralPurposeV2是存储账户类型,并非Blob类型,会导致参数错误。
3. Content-Length设置错误
手动将Content-Length设为0,与实际上传的PDF文件大小不符,会触发请求异常。该值应由浏览器自动计算,无需手动设置。
4. 冗余的x-ms-date头
使用SAS Token认证时,无需手动设置x-ms-date,SAS Token本身已包含有效期信息。
修复后的核心代码片段
修改handleFileUpload函数中的相关部分:
async function handleFileUpload(file) { if (!file) { console.error('No file selected.'); return; } const accountName = 'test'; const containerName = 'test1234'; // SAS Token需以?开头,示例:?sv=2020-04-08&ss=bfqt&srt=sco&sp=rwdlacupitfx&se=2024-05-20T00:00:00Z&st=2024-05-19T16:00:00Z&spr=https&sig=xxx const sasToken = '?sv=2020-04-08&...'; // 替换为你的有效SAS Token const blobName = file.name; const uploadUrl = `https://${accountName}.blob.core.windows.net/${containerName}/${blobName}${sasToken}`; const headers = new Headers(); // 修正Blob类型为BlockBlob headers.append('x-ms-blob-type', 'BlockBlob'); headers.append('x-ms-version', '2020-04-08'); const requestOptions = { method: 'PUT', headers: headers, body: file }; try { const response = await fetch(uploadUrl, requestOptions); if (response.ok) { console.log('File uploaded successfully'); } else { const errorText = await response.text(); console.error('Error uploading file:', response.statusText, errorText); } } catch (error) { console.error('An error occurred:', error); } // PDF预览部分保持不变... }
额外注意事项
- 确保SAS Token具备写入(w)权限,且有效期在当前时间范围内。
- SAS Token必须以
?开头,若生成时无此符号,需手动添加,否则URL解析会出错。 - 禁止在前端代码中暴露存储账户访问密钥(storageAccessKey),存在安全风险,推荐使用SAS Token或后端签名上传请求。
内容的提问来源于stack exchange,提问作者Sani
相关产品推荐
相关产品推荐

