英文:
.NET 6 API - Upload image from frontend to database
问题
我正在作为初级开发人员参与我的第一个项目,但我也被分配了创建后端 API 的任务。因此,这是我第一次接触后端,我几乎不了解 C# 或 .NET。
前端:Nextjs,typescript
后端:.NET 6,C#
问题:
用户需要能够上传图像到艺术家对象。目前,我只是使用一个表示图像在前端存储路径的字符串。
我将找出如何在前端接收图像,并在 API 中创建一个端点来上传图像。
我想要问的问题是如何在 .NET 中接收和存储图像?
艺术家实体:
namespace BookingAPI.Entities
{
public class Artist
{
public string Id { get; set; }
public string Name { get; set; } = null!;
public string Description { get; set; }
public string? Image { get; set; }
}
}
Controller 中的 CreateArtist:
// POST /events/{eventId}/program/artists
// 在 Program 中创建新的艺术家
[HttpPost]
[Route("/events/{eventId}/program/artists")]
public async Task<ActionResult<EventArtistDto>> CreateEventArtistAsync(string eventId, CreateEventArtistDto createEventArtistDto)
{
Artist artist = new()
{
Id = Guid.NewGuid().ToString(),
Name = createEventArtistDto.Name,
Description = createEventArtistDto.Description,
Image = createEventArtistDto.Image,
};
await repository.CreateEventArtistAsync(eventId, artist);
return artist.AsDto(); // 是否需要添加返回内容?
}
InMemRepository 中的 CreateArtist:
public async Task CreateEventArtistAsync(string eventId, Artist artist)
{
var eventIndex = events.FindIndex(existingEvent => existingEvent.Id == eventId);
var existingEvent = events[eventIndex];
var artists = existingEvent.EventProgram.Artists;
artists.Add(artist);
await Task.CompletedTask;
}
请让我知道是否需要上传更多代码。
我真的不确定如何开始这段代码,当然,我同时也在搜索,但我想自己提出问题,以便可能可以正确学习这个过程。
更新:
在阅读 @EminNiftiyev 的答案后,我尝试了以下代码,但遇到了错误:
Controller: "隐式类型的变量必须初始化"
InMemRepository: "无法隐式转换类型 'Microsoft.AspNetCore.Http.IFormFile' 为 'string'"
我不完全理解我在这里做什么。
Controller 中的 UpdateImageInEventArtistAsync:
// PUT /events/{eventId}/program/artists/{artistId}/image
// 更新艺术家的图像
[HttpPost]
[Route("/events/{eventId}/program/artists/{artistId}/image")]
public async Task<ActionResult<UpdateImageInEventArtistDto>>
UpdateImageInEventArtistAsync(string eventId, string artistId,
UpdateImageInEventArtistDto updateImageInEventArtistDto,
[FromForm] IFormFile file)
{
// 从事件获取节目
var program = await repository.GetEventProgramAsync(eventId);
var existingArtist = program.Artists.Where(artist => artist.Id == artistId).SingleOrDefault();
if (existingArtist is null)
{
return NotFound();
}
var byteArrayImage;
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
byteArrayImage = stream.ToArray();
}
existingArtist.Image = Convert.ToBase64String(byteArrayImage);
/* await repository.UpdateEventArtistAsync(eventId, artistId, existingArtist); */
await repository.UpdateImageInEventArtistAsync(eventId, artistId, byteArrayImage);
return NoContent();
}
InMemRepository 中的 UpdateImageInEventArtistAsync:
public async Task UpdateImageInEventArtistAsync(string eventId, string artistId, IFormFile file)
{
var eventIndex = events.FindIndex(existingEvent => existingEvent.Id == eventId);
var existingEvent = events[eventIndex];
var artists = existingEvent.EventProgram.Artists;
var existingArtist = artists.Where(artist => artist.Id == artistId).SingleOrDefault();
existingArtist.Image = file;
await Task.CompletedTask;
}
英文:
I am working on my first project as a junior developer, but i also got the task of creating the backend API. This is therefore my first time touching any backend so i almost dont know any c# or .NET.
Frontend: Nextjs, typescript
Backend: .NET 6, c#
The problem:
The users need to be able to upload an image to an artist object. As of now i am only using a string that represents the path where the image is stored in the frontend.
I will figure out how i will recieve the image in the frontend, and i will create an endpoint in the API where i can PUT the image.
The question im trying to ask is how do i do the recieving and storing of the image in the .NET?
Artist entity:
namespace BookingAPI.Entities
{
public class Artist
{
public string Id { get; set; }
public string Name { get; set; } = null!;
public string Description { get; set; }
public string? Image { get; set; }
}
}
CreateArtist in Controller
// POST /events/{eventId}/program/artists
// Create new artist in Program -> Artists
[HttpPost]
[Route("/events/{eventId}/program/artists")]
public async Task<ActionResult<EventArtistDto>> CreateEventArtistAsync(string eventId, CreateEventArtistDto createEventArtistDto)
{
Artist artist = new()
{
Id = Guid.NewGuid().ToString(),
Name = createEventArtistDto.Name,
Description = createEventArtistDto.Description,
Image = createEventArtistDto.Image,
};
await repository.CreateEventArtistAsync(eventId, artist);
return artist.AsDto(); // add return body?
}
CreateArtost in inMemRepository
public async Task CreateEventArtistAsync(string eventId, Artist artist)
{
var eventIndex = events.FindIndex(existingEvent => existingEvent.Id == eventId);
var existingEvent = events[eventIndex];
var artists = existingEvent.EventProgram.Artists;
artists.Add(artist);
await Task.CompletedTask;
}
Please let me know if i should upload more of the code.
Im really not sure even how to start this code, i am of course googling this at the same time, but though i would make my own question as well so that maybe i could learn this the proper way.
UPDATE:
After reading @EminNiftiyev answer i tried this,
but i get errors:
Controller: "Implicitly-typed variables must be initialized"
InMemRepository: "Cannot implicitly convert type 'Microsoft.AspNetCore.Http.IFormFile' to 'string'"
I dont fully understand what i am doing here.
UpdateImageInEventArtistAsync in Controller
//PUT /events/{eventId}/program/artists/{artistId}/image
// Update the Image in the Artist
[HttpPost]
[Route("/events/{eventId}/program/artists/{artistId}/image")]
public async Task<ActionResult<UpdateImageInEventArtistDto>>
UpdateImageInEventArtistAsync(string eventId, string artistId,
UpdateImageInEventArtistDto updateImageInEventArtistDto,
[FromForm] IFormFile file)
{
// Get Program from Event
var program = await repository.GetEventProgramAsync(eventId);
var existingArtist = program.Artists.Where(artist => artist.Id == artistId).SingleOrDefault();
if (existingArtist is null)
{
return NotFound();
}
var byteArrayImage;
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
byteArrayImage = stream.ToArray();
}
existingArtist.Image = Convert.ToBase64String(byteArrayImage);
/* await repository.UpdateEventArtistAsync(eventId, artistId, existingArtist); */
await repository.UpdateImageInEventArtistAsync(eventId, artistId, byteArrayImage);
return NoContent();
}
UpdateImageInEventArtistAsync in InMemRepository
public async Task UpdateImageInEventArtistAsync(string eventId, string artistId, IFormFile file)
{
var eventIndex = events.FindIndex(existingEvent => existingEvent.Id == eventId);
var existingEvent = events[eventIndex];
var artists = existingEvent.EventProgram.Artists;
var existingArtist = artists.Where(artist => artist.Id == artistId).SingleOrDefault();
existingArtist.Image = file;
await Task.CompletedTask;
}
答案1
得分: 1
首先,您创建了用于上传图像的端点。那时,完美的选择是使用 IFormFile。代码如下:
[HttpPost]
[Route("api/image/upload")]
public async Task<IActionResult> UploadImage([FromForm] IFormFile file)
{
}
然后,您可以获取图像的字节数组格式。为此,您应该使用流(Stream):
var byteArrayImage;
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
byteArrayImage = stream.ToArray();
}
这样,您现在可以获取图像的字节数组格式了。最后,您可以将其插入到数据库或其他数据源中。
这是另一种完美的实践方式。
英文:
First you create endPoint for Upload Image. That time perfectly choice is use IFormFile. Code like this
[HttpPost]
[Route("api/image/upload")]
public async Task<IActionResult> UploadImage([FromForm] IFormFile file)
{
}
Then you get image like byteArray format. For this you should use Stream
var byteArrayImage;
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
byteArrayimage = stream.ToArray();
}
Here we go. Now yo can get Image like ByteArray format. And Finally you can insert to Database or another source.
That's perfect practice from another way.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论