我有一个控制器发布方法,需要上传文件:
查看:
@using (Html.BeginForm("UploadCSV", "TemporaryPerson", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(false, "", new { @class = "text-danger" })
<br />
<input type="file" name="personFile" /><input type="submit" value="Upload" />
</div>
}
和控制器方法:
[HttpPost]
public ActionResult UploadCSV(UploadCsvViewModel model)
{
if (ModelState.IsValid)
{
using (StreamReader reader = new StreamReader(Request.Files[0].InputStream))
{
using (var csv = new CsvReader(reader))
{
var records = csv.GetRecords<TemporaryPersonCsv>().ToList();
foreach (var record in records)
{
//...................
}
}
}
}
return View();
}
它工作正常。但是我想将所有验证都移到UploadCsvViewModel:
public class UploadCsvViewModel : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (HttpContext.Current.Request.Files == null || HttpContext.Current.Request.Files.Count == 0 || HttpContext.Current.Request.Files[0].ContentLength == 0)
results.Add(new ValidationResult("File is not selected or empty", new string[] { "NoFile" }));
using (StreamReader reader = new StreamReader(HttpContext.Current.Request.Files[0].InputStream))
{
using (var csv = new CsvReader(reader))
{
var enumeraterecords = csv.GetRecords<TemporaryPersonCsv>();
if (enumeraterecords != null)
{
var records = enumeraterecords.ToList();
if (records == null || records.Count == 0)
results.Add(new ValidationResult("No records in file", new string[] { "NoRecords" }));
// different validation, according with business logic
}
else
results.Add(new ValidationResult("No records in file", new string[] { "NoRecords" }));
}
}
return results;
}
}
问题是如果我在UploadCsvViewModel中有Validate方法,那么我得到错误:
异常详细信息:CsvHelper.CsvReaderException:没有标头记录 找到。
在线:
var records = csv.GetRecords<TemporaryPersonCsv>().ToList();
在控制器方法中。我假设,InputStream的位置无效。我试过了:
复制到另一个流:
using (MemoryStream ms = new MemoryStream())
{
HttpContext.Current.Request.Files[0].InputStream.CopyTo(ms, HttpContext.Current.Request.Files[0].ContentLength);
没有帮助
在验证方法结束时将输入流位置设置为0:
HttpContext.Current.Request.Files [0] .InputStream.Position = 0;
没有帮助
为'reader'对象调用DiscardBufferedData
reader.DiscardBufferedData();
也没有帮助。
答案 0 :(得分:0)
我找到了解决方案。我将InputStream复制到另一个流(即MemoryStream),然后我可以为两个流(InputStream和MemoryStream)设置Position = 0并且它可以工作。
验证方法:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (HttpContext.Current.Request.Files == null || HttpContext.Current.Request.Files.Count == 0 || HttpContext.Current.Request.Files[0].ContentLength == 0)
results.Add(new ValidationResult("File is not selected or empty", new string[] { "NoFile" }));
using (MemoryStream ms = new MemoryStream())
{
HttpContext.Current.Request.Files[0].InputStream.CopyTo(ms);
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
using (var csv = new CsvReader(reader))
{
var enumeraterecords = csv.GetRecords<TemporaryPersonCsv>();
if (enumeraterecords != null)
{
var records = enumeraterecords.ToList();
if (records == null || records.Count == 0)
results.Add(new ValidationResult("No records in file", new string[] { "NoRecords" }));
// find dublicates in CSV file
var dublicates = (records.GroupBy(p => p.Fullname.ToLower().Trim()).Where(p => p.Count() > 1).Select(p => p.Key)).ToList();
if (dublicates != null && dublicates.Count > 0)
{
foreach (var dublicateFullname in dublicates)
{
results.Add(new ValidationResult(String.Concat("There are 2 or more records with fullname='", dublicateFullname, "' in your csv file. Please, fix your file and upload again."), new string[] { "DublicateRecords" }));
}
}
// find dublicates in TemporaryPersons and Persons tables
PlugandabandonEntities db = new PlugandabandonEntities();
foreach (var record in records)
{
if (db.TemporaryPerson.Where(p => p.Fullname.ToLower() == record.Fullname.ToLower()).Count() > 0)
results.Add(new ValidationResult(String.Concat("Record with fullname='", record.Fullname, "' already exists in TemporaryPersons. Please, fix your file and upload again."), new string[] { "RecordExistsInTemporaryPerson" }));
if (db.Person.Where(p => p.Fullname.ToLower() == record.Fullname.ToLower()).Count() > 0)
results.Add(new ValidationResult(String.Concat("Record with fullname='", record.Fullname, "' already exists in Persons. Please, fix your file and upload again."), new string[] { "RecordExistsInPersons" }));
}
}
else
results.Add(new ValidationResult("No records in file", new string[] { "NoRecords" }));
}
reader.DiscardBufferedData();
}
}
HttpContext.Current.Request.Files[0].InputStream.Position = 0;
return results;
}
然后我们在控制器方法中有一个“处女”的InputStream,我们可以随意使用它;)