How upload csv file and parse it?
我需要上传csv文件并解析它。我可以在HTTP主体请求中看到文件,但是当我在CSVReader中传递它时,我可以看到base64字符串状的头文件:
在客户端,我使用AngularJS:
1 2 3 4 5 6 7 8 | 'uploadBulkUsersFile': { method: 'POST', url: CONFIG.apiServiceBaseUri +"api/users/bulkUsers", headers: { "Content-Type": undefined }, transformRequest: angular.identity, withCredentials: true }, |
并致电:
1 2 3 4 5 6 7 8 | var _uploadBulkUsersFile = function (bulkUsersFile) { var fd = new FormData(); fd.append("file", bulkUsersFile); return usersResource.uploadBulkUsersFile({}, fd, function (result) { return result; }).$promise; }; |
在服务器端,我使用WebAPI2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | if (!Request.Content.IsMimeMultipartContent()) throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); foreach (var file in provider.Contents) { var buffer = await file.ReadAsStreamAsync(); TextReader textReader = new StreamReader(buffer); var csv = new CsvReader(textReader); var records = csv.GetRecords<BulkUploadUser>().ToList(); return Created("DefaultApi", records); } |
HTTP请求负载
------webkitformboundaryskplgjrinomnpxvp(webkitformboundaryskplgjrinomnpxvp)内容处置:表单数据;name="file"
1 2 | data:application/vnd.ms-excel;base64,RW1haWwsRmlyc3ROYW1lLExhc3ROYW1lDQpwcm9zdG8uZHVkYUBnbWFpbC5jb20yLERlbmlzLER1ZGFpZXYNCnByb3N0by5kdWRhQGdtYWlsLmNvbSxEZW5pcyxEdWRhaWV2DQpwcm9zdG8uZHVkYUBnbWFpbC5jb20yLERlbmlzLER1ZGFpZXYNCg== ------WebKitFormBoundarySKPlgJRINOMnpxVP-- |
更新
@Ubercode建议我将base 64转换为string,我做到了,但看起来很恶心:
1 2 3 4 5 6 7 8 9 10 | var buffer = await file.ReadAsStreamAsync(); TextReader textReader = new StreamReader(buffer); var text = textReader.ReadToEnd(); var indexOfWord ="base64,"; var base64EncodedBytes = System.Convert.FromBase64String(text.Substring(text.IndexOf(indexOfWord) + indexOfWord.Length)); var encoded = System.Text.Encoding.UTF8.GetString(base64EncodedBytes); TextReader textReader2 = new StringReader(encoded); var csv = new CsvReader(textReader2); var records = csv.GetRecords<BulkUploadUser>().ToList(); |
您需要将base64编码的内容解码到您的文件中:
如何对base 64字符串进行编码和解码
您可以稍微整理一下代码,这样:
1 2 3 4 5 6 7 8 9 10 11 12 | string text; using(TextReader textReader = new StreamReader(buffer)) text = textReader.ReadToEnd(); CsvReader csv; using(var ms = new MemoryStream(Convert.FromBase64String(text.Substring(text.IndexOf(',') + 1))) using (var textReader2 = new StreamReader(ms)) csv = new CsvReader(textReader2); var records = csv.GetRecords<BulkUploadUser>().ToList(); |
我也有同样的问题,谢谢你在这篇文章中的建议。
首先,上传一个文件有两种可能:HTTPPOST内容或表单数据(也是POST,但不完全相同)。
我使用的是更简单的方法,HTTP Post内容。base64编码等没有问题,解决方案仍然很简单,但我认为对于大文件来说,这可能是非常无用的。
我在Angular项目中使用了以下代码:
角度编码
导入对话框(HTML):
1 2 3 4 | <input hidden #imageInput type="file" accept=".csv" (change)="processFile(imageInput)"> <button mat-button class="image-upload-button full-width" (click)="imageInput.click()"> <mat-icon>add</mat-icon> </button> |
对话代码(.ts)
1 2 | const file: File = imageInput.files[0]; this.dialogRef.close(file); |
对话框关闭后执行的TS代码
1 2 | const url = 'myapi/Import'; return this.http.post<ImportResult>(url, file).toPromise(); |
C码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | try { var result = new ImportResult(); s = System.Web.HttpContext.Current.Request.GetBufferedInputStream(); using (var sr = new System.IO.StreamReader(s)) { s = null; var reader = new CsvReader(sr, new CsvConfiguration { Delimiter =";" }); var records = reader.GetRecords<RowEntry>(); ... } return result; } finally { s?.Dispose(); } |
希望这会有所帮助,这是一个简单的解决方案,可以很好地工作。
上传的数据确实是csv,而不是excel:
1 2 3 4 | Email,FirstName,LastName prosto.duda@gmail.com2,Denis,Dudaiev prosto.duda@gmail.com,Denis,Dudaiev prosto.duda@gmail.com2,Denis,Dudaiev |
最好首先防止数据转换为base64(它更大,需要解码)。
出于某种原因,数据以"excel"的形式发送,并以base64的形式发送:
1 | data:application/vnd.ms-excel;base64, |
因此,您可能需要检查以下内容:
1 2 3 4 | headers: { "Content-Type": undefined }, transformRequest: angular.identity, |
我不知道AngularJS,但你可能想把
或者在这里转换成base64:
1 2 |
所以最好检查数据在哪里转换,并将其修复为发送纯文本。这将阻止编码/解码步骤,数据也将变小。
1 2 3 4 5 6 7 8 | if (!Request.Content.IsMimeMultipartContent()) { return StatusCode(HttpStatusCode.UnsupportedMediaType); } HttpPostedFile uploadedFile = HttpContext.Current.Request.Files[0]; var csv = new CsvReader(uploadedFile.InputStream); |