使用Azure.Storage.Blobs上传邮件PDF至Blob后无法读取求助
问题:上传至Azure Blob的PDF附件损坏无法打开
上传后用Acrobat Reader打开PDF时出现报错:
Adobe Acrobat Reader could not open 'file.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).
已设置容器公共访问策略为PublicAccessType.Blob,也尝试指定ContentType为application/pdf,但问题依旧。当前代码如下:
BlobServiceClient blobServiceClient = new BlobServiceClient(connString); Attachment attachment = GetEmailPDF(emails); try { BlobContainerClient blobContainer = blobServiceClient.GetBlobContainerClient(blobDirectoryName); if (blobContainer.Exists()) { blobContainer.SetAccessPolicyAsync(PublicAccessType.Blob).Wait(); string prefix_path = <my custom prefix path setup>; var blobClient = blobContainer.GetBlobClient(prefix_path); //Upload PDF file BlobHttpHeaders blobHttpHeaders = new BlobHttpHeaders(); blobHttpHeaders.ContentType = attachment.ContentType.ToString(); blobClient.UploadAsync(attachment.ContentStream, blobHttpHeaders).Wait(); } } catch (Exception e) { throw new Exception("Something happened to UploadPDFFile: ", e); }
解决办法
1. 重置MemoryStream的位置
邮件附件的ContentStream可能已经被读取过(比如解析邮件时),此时Stream的Position不在起始位置,上传时会从当前位置开始写入,导致文件内容缺失损坏。上传前必须重置位置:
attachment.ContentStream.Position = 0;
2. 直接指定正确的ContentType
不要依赖attachment.ContentType.ToString(),邮件中的ContentType可能包含额外参数(比如application/pdf; name="file.pdf"),直接硬设为标准值更可靠:
blobHttpHeaders.ContentType = "application/pdf";
3. 改用async/await替代.Wait()
同步阻塞异步方法(.Wait())可能引发死锁或异常处理问题,建议重构为异步代码:
BlobServiceClient blobServiceClient = new BlobServiceClient(connString); Attachment attachment = GetEmailPDF(emails); try { BlobContainerClient blobContainer = blobServiceClient.GetBlobContainerClient(blobDirectoryName); if (await blobContainer.ExistsAsync()) { await blobContainer.SetAccessPolicyAsync(PublicAccessType.Blob); string prefix_path = <my custom prefix path setup>; var blobClient = blobContainer.GetBlobClient(prefix_path); // 重置流位置 attachment.ContentStream.Position = 0; BlobHttpHeaders blobHttpHeaders = new BlobHttpHeaders(); blobHttpHeaders.ContentType = "application/pdf"; await blobClient.UploadAsync(attachment.ContentStream, blobHttpHeaders); } } catch (Exception e) { throw new Exception("Something happened to UploadPDFFile: ", e); }
额外检查点
- 确认
GetEmailPDF方法返回的Attachment.ContentStream是完整的PDF内容,可以先将Stream保存到本地文件验证是否能正常打开,排除邮件解析阶段的问题。 - 上传后在Azure Portal中下载Blob,检查文件大小是否和本地附件一致,若大小为0或远小于原文件,说明流位置问题未解决。
内容的提问来源于stack exchange,提问作者Việt Tùng Nguyễn
相关产品推荐
相关产品推荐

