C# 从物理文件实例化文件
我有一个物理文件,我想将它传递给我的控制器方法,该方法需要C# 从物理文件实例化文件,c#,asp.net,unit-testing,asp.net-core,C#,Asp.net,Unit Testing,Asp.net Core,我有一个物理文件,我想将它传递给我的控制器方法,该方法需要ifformfile类型(用于单元测试) 我找不到任何实例化ifformfile接口的类,这意味着我无法创建一个类 如何将物理文件转换为ifformfile?假设您有一个接受ifforminfo的控制器方法 [HttpPost] public Task<IActionResult> Upload(IFormFile file) { FileDetails fileDetails = null; using (
ifformfile
类型(用于单元测试)
我找不到任何实例化ifformfile
接口的类,这意味着我无法创建一个类
如何将物理文件转换为
ifformfile
?假设您有一个接受ifforminfo
的控制器方法
[HttpPost]
public Task<IActionResult> Upload(IFormFile file) {
FileDetails fileDetails = null;
using (var reader = new StreamReader(file.OpenReadStream())) {
var fileContent = reader.ReadToEnd();
ContentDispositionHeaderValue parsedContentDisposition = null;
if (ContentDispositionHeaderValue.TryParse(file.ContentDisposition, out parsedContentDisposition)) {
fileDetails = new FileDetails {
Filename = parsedContentDisposition.FileName,
Content = fileContent
};
}
}
return Task.FromResult((IActionResult)fileDetails);
}
模拟的排列甚至可以提取为可重用的扩展方法
public static IFormFile AsMockIFormFile(this FileInfo physicalFile) {
var fileMock = new Mock<IFormFile>();
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
writer.Write(physicalFile.OpenRead());
writer.Flush();
ms.Position = 0;
var fileName = physicalFile.Name;
//Setup mock file using info from physical file
fileMock.Setup(_ => _.FileName).Returns(fileName);
fileMock.Setup(_ => _.Length).Returns(ms.Length);
fileMock.Setup(m => m.OpenReadStream()).Returns(ms);
fileMock.Setup(m => m.ContentDisposition).Returns(string.Format("inline; filename={0}", fileName));
//...setup other members (code removed for brevity)
return fileMock.Object;
}
您可以实例化一个。它实现了格式文件
.Net Core 3.1中的示例(假设“文件”是物理路径和文件):
我尝试了Nkosi的答案(使用.NETCore3.1),但它只会返回“System.IO.FileStream”作为文件内容!可能是因为它正在将FileStream对象从physicalFile.OpenRead()写入输出流,而不是流的实际内容。这个修改过的版本适合我:
public static IFormFile AsMockIFormFile(this FileInfo physicalFile)
{
var fileMock = new Mock<IFormFile>();
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
using (FileStream fs = physicalFile.OpenRead())
{
byte[] b = new byte[1024];
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b, 0, b.Length) > 0)
{
writer.WriteLine(temp.GetString(b));
}
}
writer.Flush();
ms.Position = 0;
var fileName = physicalFile.Name;
//Setup mock file using info from physical file
fileMock.Setup(_ => _.FileName).Returns(fileName);
fileMock.Setup(_ => _.Length).Returns(ms.Length);
fileMock.Setup(m => m.OpenReadStream()).Returns(ms);
fileMock.Setup(m => m.ContentDisposition).Returns(string.Format("inline; filename={0}", fileName));
//...setup other members as needed
return fileMock.Object;
}
publicstaticiformfile AsMockIFormFile(此FileInfo物理文件)
{
var fileMock=new Mock();
var ms=新内存流();
var writer=新的StreamWriter(毫秒);
使用(FileStream fs=physicalFile.OpenRead())
{
字节[]b=新字节[1024];
UTF8Encoding temp=新的UTF8Encoding(真);
而(fs.Read(b,0,b.Length)>0)
{
writer.WriteLine(临时GetString(b));
}
}
writer.Flush();
ms.Position=0;
var fileName=physicalFile.Name;
//使用物理文件中的信息设置模拟文件
fileMock.Setup(=>quot.FileName).Returns(FileName);
fileMock.Setup(=>979;.Length).Returns(ms.Length);
Setup(m=>m.OpenReadStream()).Returns(ms);
Setup(m=>m.ContentDisposition).Returns(string.Format(“inline;filename={0}”,filename));
//…根据需要设置其他成员
返回fileMock.Object;
}
这里有一个,但它位于内部名称空间中,因此您不应该真正使用它。如果这是用于单元测试,则可以模拟接口或实现用于测试目的的自己的类。这看起来没问题,但如果尝试序列化fileMock.Object,则会出现异常我们是否应该使用具有内部名称空间的类?看起来FormFile在.Net Core 2中是内部的,现在已在.Net Core 3+中公开。还要注意,在某些情况下,例如,在使用DocumentFormat.OpenXml包处理文件时,我还必须添加以下行:physicalFile.IsReadOnly=true代码>
var physicalFile = new FileInfo("filePath");
IFormFile formFile = physicalFile.AsMockIFormFile();
using var stream = new MemoryStream(File.ReadAllBytes(file).ToArray());
var formFile = new FormFile(stream, 0, stream.Length, "streamFile", file.Split(@"\").Last());
public static IFormFile AsMockIFormFile(this FileInfo physicalFile)
{
var fileMock = new Mock<IFormFile>();
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
using (FileStream fs = physicalFile.OpenRead())
{
byte[] b = new byte[1024];
UTF8Encoding temp = new UTF8Encoding(true);
while (fs.Read(b, 0, b.Length) > 0)
{
writer.WriteLine(temp.GetString(b));
}
}
writer.Flush();
ms.Position = 0;
var fileName = physicalFile.Name;
//Setup mock file using info from physical file
fileMock.Setup(_ => _.FileName).Returns(fileName);
fileMock.Setup(_ => _.Length).Returns(ms.Length);
fileMock.Setup(m => m.OpenReadStream()).Returns(ms);
fileMock.Setup(m => m.ContentDisposition).Returns(string.Format("inline; filename={0}", fileName));
//...setup other members as needed
return fileMock.Object;
}