使用C#读取Amazon S3存储桶Excel文件并解决流转换相关问题
问题原因
- 代码中先调用
reader.ReadToEnd()已将流指针移动到末尾,后续执行reader.ReadLine()时没有剩余内容可读取,因此只会返回null - Excel文件属于二进制文件:.xlsx本质是ZIP压缩包(你看到的
PK\u0003\u0004就是ZIP文件的头标识),.xls是专有二进制格式,都不能用StreamReader按普通文本的方式读取,强行用文本读取不仅会得到乱码,还可能触发读取异常导致超时 - 你当前的读取逻辑是按CSV文本文件设计的,完全不适用Excel格式的文件
实现方案
方案1:读取Excel流直接转换为DataTable
使用常用Excel处理库即可实现,不需要将流落地到本地文件,直接处理S3返回的响应流即可:
处理.xlsx格式(EPPlus实现)
using Amazon.S3; using Amazon.S3.Model; using OfficeOpenXml; using System.Data; // EPPlus 5+ 版本需要声明证书上下文,非商业用途可设置为NonCommercial ExcelPackage.LicenseContext = LicenseContext.NonCommercial; using (var _client = new AmazonS3Client(accKey, secKey, Amazon.RegionEndpoint.USEast1)) using (var response1 = await _client.GetObjectAsync("rrrrr","mmm.xlsx")) using (var responseStream = response1.ResponseStream) using (var excelPackage = new ExcelPackage(responseStream)) { var title = response1.Metadata["x-amz-meta-title"]; var contentType = response1.Headers["Content-Type"]; DataTable dt = new DataTable(); // 取第一个工作表,可按需修改索引或按名称取 var worksheet = excelPackage.Workbook.Worksheets.FirstOrDefault(); if (worksheet == null) return dt; // 加载表头 for (int col = 1; col <= worksheet.Dimension.End.Column; col++) { dt.Columns.Add(worksheet.Cells[1, col].Text?.ToString() ?? $"列{col}"); } // 加载行数据,从第二行开始(第一行是表头) for (int row = 2; row <= worksheet.Dimension.End.Row; row++) { DataRow dr = dt.NewRow(); for (int col = 1; col <= worksheet.Dimension.End.Column; col++) { dr[col - 1] = worksheet.Cells[row, col].Text?.ToString(); } dt.Rows.Add(dr); } // 此处dt就是转换完成的DataTable }
处理.xls格式(NPOI实现)
如果你的文件是旧版的.xls格式,替换为NPOI库处理即可,核心逻辑一致,直接读取响应流解析Excel结构。
方案2:将Excel流转为字符串(仅用于文件转码传输/存储)
如果你的需求不是提取Excel内容,而是需要把整个Excel文件的二进制内容转为可传输的字符串,需要用Base64编码,不能直接用文本读取器读取:
using (var _client = new AmazonS3Client(accKey, secKey, Amazon.RegionEndpoint.USEast1)) using (var response1 = await _client.GetObjectAsync("rrrrr","mmm.xls")) using (var responseStream = response1.ResponseStream) using (var ms = new MemoryStream()) { await responseStream.CopyToAsync(ms); byte[] fileBytes = ms.ToArray(); // 得到Base64格式的文件字符串,可用于传输、存储,需要恢复文件时转成字节数组即可 string fileBase64Str = Convert.ToBase64String(fileBytes); }
内容的提问来源于stack exchange,提问作者Abhishek V
相关产品推荐
相关产品推荐

