如何在.NET Core 6 Web Api中启用文件上传,作为IFormFile存储在SQL VarBinary中-使



我以前从未做过这样的事情,我很难找到问题的答案(也不知道该问什么问题会让问题变得更难(。

我有一个.NETCore6Webneneneba API,它连接到一个SQLExpressDB(我使用EF和AutoMapper(。

我有一个模型

public partial class ConcessionDocument
{
public long Id { get; set; }
public long RequestId { get; set; }
public int LineNumber { get; set; }
public IFormFile ConcessionDoc { get; set; } = null!;
public virtual RequestLine RequestLine { get; set; } = null!;
}

和我的数据库上下文

modelBuilder.Entity<ConcessionDocument>(entity =>
{
entity.HasKey(e => new { e.RequestId, e.LineNumber })
.HasName("PK_RMR_CONCESSIONDOCUMENT");
entity.ToTable("ConcessionDocument", "rmr");
entity.Property(e => e.Id);
entity.Property(e => e.ConcessionDoc);
entity.HasOne(d => d.RequestLine)
.WithOne(p => p.ConcessionDocument)
.HasForeignKey<RequestLine>(d => new { d.RequestId, d.LineNumber })
.HasConstraintName("FK_RMR_REQUESTLINE_CONCESSIONDOCUMENT");
});

和我的数据库表

CREATE TABLE [rmr].[ConcessionDocument]
(
[Id] BIGINT NOT NULL IDENTITY(1,1), 
[RequestId] BIGINT NOT NULL, 
[LineNumber] INT NOT NULL, 
[ConcessionDoc] VARBINARY(MAX) NOT NULL
CONSTRAINT PK_RMR_CONCESSIONDOCUMENT
--PRIMARY KEY ([RequestId], [LineNumber]),
PRIMARY KEY ([Id])
CONSTRAINT FK_RMR_REQUESTLINE_CONCESSIONDOCUMENT
FOREIGN KEY (RequestId, LineNumber)
REFERENCES rmr.RequestLine(RequestId, LineNumber),
)

现在我正在控制器中使用POST方法。我已经使用了AutoMapper,我需要做的其他一切都很好,我已经理解并能够让它工作。我现在需要能够上传小文件,而这正是我苦苦挣扎的地方。我的理解是文件<2mb可以进入数据库,这是我想采取的方法,因为不会有很多。

根据我目前所读到的内容,我需要将IFormFile ConcessionDoc属性转换为内存流,以便能够将其作为varbinary保存在数据库中。

[HttpPost]
public async Task<ActionResult<ConcessionDocumentCreateDTO>> PostConcessionDoc(ConcessionDocumentCreateDTO concessionDocDto)
{
var conDoc = _mapper.Map<ConcessionDocument>(concessionDocDto);
Byte[]? bytes = null;
if (_context.ConcessionDocument == null)
{
return Problem("Entity set 'RawcliffeDatastoreContext.ConcessionDocument'  is null.");
}
await _context.ConcessionDocument.AddAsync(conDoc);
try
{
using (MemoryStream ms = new MemoryStream())
{
if(conDoc.ConcessionDoc != null)
{
conDoc.ConcessionDoc.OpenReadStream().CopyTo(ms);
}
bytes = ms.ToArray();
}
await _context.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (ConcessionDocExists(conDoc.Id))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtAction(nameof(GetConcessionDoc), new { id = conDoc.Id }, conDoc);
}

以上就是我到目前为止所拥有的——这与我的其他控制器遵循相同的格式,只是添加了设置内存流(作为字节变量(。

我不知道从这里到哪里去。

我认为我需要以某种方式覆盖AutoMapper正在做的事情,将字节映射到ConcessionDoc属性。

有人知道我会怎么做吗?此外,如果这是完全不正确的,我走错了路等,请告诉我。欢迎任何建议。

到目前为止,您做得很好,只需要做一些调整。

IFormFile是一个接口,所以您并不希望它出现在EF实体上,因此,由于它是一个varbinary,您应该将其作为byte[]

我认为我需要以某种方式覆盖AutoMapper正在做的事情,将字节映射到ConcessionDoc属性。

是的,您可以在执行_mapper.Map之后更新conDoc变量。

你可以做conDoc.ConcessionDoc = ms.ToArray();,而不是做bytes = ms.ToArray();

最新更新