如何上传csv文件并解析它?
How upload csv file and parse it?
我需要上传 csv 文件并解析它。
我可以在 http body 请求中看到文件,但是当我在 csvreader 中传递它时,我可以看到像 headers 这样的 base64 字符串:
在客户端我使用 angularjs:
'uploadBulkUsersFile': {
method: 'POST', url: CONFIG.apiServiceBaseUri + "api/users/bulkUsers",
headers: {
"Content-Type": undefined
},
transformRequest: angular.identity,
withCredentials: true
},
并调用:
var _uploadBulkUsersFile = function (bulkUsersFile) {
var fd = new FormData();
fd.append("file", bulkUsersFile);
return usersResource.uploadBulkUsersFile({}, fd, function (result) {
return result;
}).$promise;
};
在服务器端我使用 webapi2:
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
Content-Disposition: form-data;名字="file"
data:application/vnd.ms-excel;base64,RW1haWwsRmlyc3ROYW1lLExhc3ROYW1lDQpwcm9zdG8uZHVkYUBnbWFpbC5jb20yLERlbmlzLER1ZGFpZXYNCnByb3N0by5kdWRhQGdtYWlsLmNvbSxEZW5pcyxEdWRhaWV2DQpwcm9zdG8uZHVkYUBnbWFpbC5jb20yLERlbmlzLER1ZGFpZXYNCg==
------WebKitFormBoundarySKPlgJRINOMnpxVP--
更新
@Ubercode 建议我将 base 64 转换为字符串,我做到了,但是看起来很恶心:
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();
if (!Request.Content.IsMimeMultipartContent())
{
return StatusCode(HttpStatusCode.UnsupportedMediaType);
}
HttpPostedFile uploadedFile = HttpContext.Current.Request.Files[0];
var csv = new CsvReader(uploadedFile.InputStream);
您需要将 base64 编码的内容解码到您的文件中:
How do I encode and decode a base 64 string
您可以这样稍微整理一下代码:
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();
上传的数据确实是csv,不是excel:
Email,FirstName,LastName
prosto.duda@gmail.com2,Denis,Dudaiev
prosto.duda@gmail.com,Denis,Dudaiev
prosto.duda@gmail.com2,Denis,Dudaiev
最好在一开始就防止数据被转换为base64(它更大,需要解码)。
出于某种原因,数据以 'excel' 和 base64 格式发送:
data:application/vnd.ms-excel;base64,
所以您可能需要检查以下内容:
headers: {
"Content-Type": undefined
},
transformRequest: angular.identity,
我不知道 AngularJS,但您可能想将 Content-Type
更改为 text/csv
并检查 transformRequest
。
或者可能在此处转换为 base64:
var fd = new FormData();
fd.append("file", bulkUsersFile);
因此最好检查数据转换的位置并将其修复为发送纯文本。这将避免 encoding/decoding 步骤,数据也会变小。
刚遇到同样的问题,感谢post中的建议。
首先,上传文件有两种可能:Http-POST-Content or form-data(也是post,但不一样)
我正在使用更简单的方法,即 Http-POST-Content。 base64 编码等没有问题,解决方案很简单,但是我认为对于大文件来说它可能非常低效。
我在 angular 项目中使用了以下代码:
Angular代码
导入对话框(html):
<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)
const file: File = imageInput.files[0];
this.dialogRef.close(file);
ts-对话框关闭后执行的代码
const url = 'myapi/Import';
return this.http.post<ImportResult>(url, file).toPromise();
C#代码
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 文件并解析它。
我可以在 http body 请求中看到文件,但是当我在 csvreader 中传递它时,我可以看到像 headers 这样的 base64 字符串:
在客户端我使用 angularjs:
'uploadBulkUsersFile': {
method: 'POST', url: CONFIG.apiServiceBaseUri + "api/users/bulkUsers",
headers: {
"Content-Type": undefined
},
transformRequest: angular.identity,
withCredentials: true
},
并调用:
var _uploadBulkUsersFile = function (bulkUsersFile) {
var fd = new FormData();
fd.append("file", bulkUsersFile);
return usersResource.uploadBulkUsersFile({}, fd, function (result) {
return result;
}).$promise;
};
在服务器端我使用 webapi2:
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 Content-Disposition: form-data;名字="file"
data:application/vnd.ms-excel;base64,RW1haWwsRmlyc3ROYW1lLExhc3ROYW1lDQpwcm9zdG8uZHVkYUBnbWFpbC5jb20yLERlbmlzLER1ZGFpZXYNCnByb3N0by5kdWRhQGdtYWlsLmNvbSxEZW5pcyxEdWRhaWV2DQpwcm9zdG8uZHVkYUBnbWFpbC5jb20yLERlbmlzLER1ZGFpZXYNCg==
------WebKitFormBoundarySKPlgJRINOMnpxVP--
更新
@Ubercode 建议我将 base 64 转换为字符串,我做到了,但是看起来很恶心:
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();
if (!Request.Content.IsMimeMultipartContent())
{
return StatusCode(HttpStatusCode.UnsupportedMediaType);
}
HttpPostedFile uploadedFile = HttpContext.Current.Request.Files[0];
var csv = new CsvReader(uploadedFile.InputStream);
您需要将 base64 编码的内容解码到您的文件中:
How do I encode and decode a base 64 string
您可以这样稍微整理一下代码:
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();
上传的数据确实是csv,不是excel:
Email,FirstName,LastName
prosto.duda@gmail.com2,Denis,Dudaiev
prosto.duda@gmail.com,Denis,Dudaiev
prosto.duda@gmail.com2,Denis,Dudaiev
最好在一开始就防止数据被转换为base64(它更大,需要解码)。
出于某种原因,数据以 'excel' 和 base64 格式发送:
data:application/vnd.ms-excel;base64,
所以您可能需要检查以下内容:
headers: {
"Content-Type": undefined
},
transformRequest: angular.identity,
我不知道 AngularJS,但您可能想将 Content-Type
更改为 text/csv
并检查 transformRequest
。
或者可能在此处转换为 base64:
var fd = new FormData();
fd.append("file", bulkUsersFile);
因此最好检查数据转换的位置并将其修复为发送纯文本。这将避免 encoding/decoding 步骤,数据也会变小。
刚遇到同样的问题,感谢post中的建议。
首先,上传文件有两种可能:Http-POST-Content or form-data(也是post,但不一样)
我正在使用更简单的方法,即 Http-POST-Content。 base64 编码等没有问题,解决方案很简单,但是我认为对于大文件来说它可能非常低效。
我在 angular 项目中使用了以下代码:
Angular代码
导入对话框(html):
<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)
const file: File = imageInput.files[0];
this.dialogRef.close(file);
ts-对话框关闭后执行的代码
const url = 'myapi/Import';
return this.http.post<ImportResult>(url, file).toPromise();
C#代码
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();
}
希望这会有所帮助,这是一个工作正常的简单解决方案。