Как загрузить файлы в ядре asp.net?

Как загрузить файлы или изображения, используя Asp.net MVC 6 с некоторыми данными модели? Например, у меня есть такая форма;

<form>
    <input type="file">
    <input type="text" placeholder="Image name...">
    <input type="text" placeholder="Image description...">
    <input type="submit" value="Submit">
</form>

Я прочитал много Учебников о том, как загрузить, но я не вижу ничего загружающего с некоторыми данными, такими как форма выше.

Кроме того, есть ли какая-либо библиотека для манипулирования изображениями для изменения размера и нанесения водяных знаков, такая же, как в классе манипулирования изображениями Codeigniter? (https://codeigniter.com/user_guide/libraries/image_lib.html

Ответ 1

Вы можете добавить новое свойство типа IFormFile в модель представления

public class CreatePost
{
   public string ImageCaption { set;get; }
   public string ImageDescription { set;get; }
   public IFormFile MyImage { set; get; }
}

и в вашем методе действия GET мы создадим объект этой модели представления и отправим в представление.

public IActionResult Create()
{
   return View(new CreatePost());
}

Теперь в вашем Создать вид, который сильно типизированных на наш взгляд, модели, имеют form тег, который имеет enctype набор атрибутов для "multipart/form-data"

@model CreatePost
<form asp-action="Create" enctype="multipart/form-data">   

    <input asp-for="ImageCaption"/>
    <input asp-for="ImageDescription"/>
    <input asp-for="MyImage"/>

    <input type="submit"/>
</form>

И ваше действие HttpPost для обработки отправки формы

[HttpPost]
public IActionResult Create(CreatePost model)
{
   var img = model.MyImage;
   var imgCaption = model.ImageCaption;

   //Getting file meta data
   var fileName = Path.GetFileName(model.MyImage.FileName);
   var contentType = model.MyImage.ContentType;

   // do something with the above data
   // to do : return something
}

Если вы хотите загрузить файл в какой-либо каталог своего приложения, вы должны использовать IHostingEnvironment чтобы получить путь к IHostingEnvironment. Вот рабочий образец.

public class HomeController : Controller
{
    private readonly IHostingEnvironment hostingEnvironment;
    public HomeController(IHostingEnvironment environment)
    {
        hostingEnvironment = environment;
    }
    [HttpPost]
    public IActionResult Create(CreatePost model)
    {
        // do other validations on your model as needed
        if (model.MyImage != null)
        {
            var uniqueFileName = GetUniqueFileName(model.MyImage.FileName);
            var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
            var filePath = Path.Combine(uploads,uniqueFileName);
            model.MyImage.CopyTo(new FileStream(filePath, FileMode.Create)); 

            //to do : Save uniqueFileName  to your db table   
        }
        // to do  : Return something
        return RedirectToAction("Index","Home");
    }
    private string GetUniqueFileName(string fileName)
    {
        fileName = Path.GetFileName(fileName);
        return  Path.GetFileNameWithoutExtension(fileName)
                  + "_" 
                  + Guid.NewGuid().ToString().Substring(0, 4) 
                  + Path.GetExtension(fileName);
    }
}

Это сохранит файл в папке uploads каталоге wwwwroot вашего приложения со случайным именем файла, сгенерированным с помощью Guids (для предотвращения перезаписи файлов с тем же именем)

Здесь мы используем очень простой метод GetUniqueName который добавляет 4 символа из guid в конец имени файла, чтобы сделать его несколько уникальным. Вы можете обновить метод, чтобы сделать его более сложным по мере необходимости.

Стоит ли хранить полный URL-адрес загруженного изображения в базе данных?

Нет. Не храните полный URL-адрес изображения в базе данных. Что если завтра ваш бизнес решит изменить название вашей компании/продукта с www.thefacebook.com на www.facebook.com? Теперь вы должны исправить все URL в таблице!

Что вы должны хранить?

Вы должны сохранить уникальное имя файла, которое вы сгенерировали выше (uniqueFileName uniqueFileName мы использовали выше), чтобы сохранить имя файла. Если вы хотите отобразить изображение обратно, вы можете использовать это значение (имя файла) и построить URL для изображения.

Например, вы можете сделать это по вашему мнению.

@{
    var imgFileName = "cats_46df.png";
}
<img src="~/uploads/@imgFileName"  alt="my img"/>

Я просто жестко закодировал имя изображения в переменную imgFileName и использовал его. Но вы можете прочитать имя сохраненного файла из вашей базы данных и установить его в свойстве модели представления и использовать его. Что-то вроде

<img src="~/uploads/@Model.FileName"  alt="my img"/>

Сохранение изображения в таблицу

Если вы хотите сохранить файл как bytearray/varbinary в вашей базе данных, вы можете преобразовать объект IFormFile в байтовый массив следующим образом

private byte[] GetByteArrayFromImage(IFormFile file)
{
    using (var target = new MemoryStream())
    {
        file.CopyTo(target);
        return target.ToArray();
    }
}

Теперь в вашем методе http post action вы можете вызвать этот метод для генерации байтового массива из IFormFile и использовать его для сохранения в вашей таблице. Приведенный ниже пример пытается сохранить объект сущности Post с использованием платформы сущностей.

[HttpPost]
public IActionResult Create(CreatePost model)
{
    //Create an object of your entity class and map property values
    var post=new Post() { ImageCaption = model.ImageCaption };

    if (model.MyImage != null)
    {
       post.Image =  GetByteArrayFromImage(model.MyImage);
    }
    _context.Posts.Add(post);
    _context.SaveChanges();
    return RedirectToAction("Index","Home");
}

Ответ 2

 <form class="col-xs-12" method="post" action="/News/AddNews" enctype="multipart/form-data">

     <div class="form-group">
        <input type="file" class="form-control" name="image" />
     </div>

     <div class="form-group">
        <button type="submit" class="btn btn-primary col-xs-12">Add</button>
     </div>
  </form>

Мое действие -

        [HttpPost]
        public IActionResult AddNews(IFormFile image)
        {
            Tbl_News tbl_News = new Tbl_News();
            if (image!=null)
            {

                //Set Key Name
                string ImageName= Guid.NewGuid().ToString() + Path.GetExtension(image.FileName);

                //Get url To Save
                string SavePath = Path.Combine(Directory.GetCurrentDirectory(),"wwwroot/img",ImageName);

                using(var stream=new FileStream(SavePath, FileMode.Create))
                {
                    image.CopyTo(stream);
                }
            }
            return View();
        }

Ответ 3

Вы можете попробовать ниже код

1- модель или вид модели

public class UploadImage 
{
  public string ImageFile { get; set; }
  public string ImageName { get; set; }
  public string ImageDescription { get; set; }
}

2- Просмотр страницы

<form class="form-horizontal" asp-controller="Image" asp-action="UploadImage" method="POST" enctype="multipart/form-data">

<input type="file" asp-for="ImageFile">
<input type="text" asp-for="ImageName">
<input type="text" asp-for="ImageDescription">
</form>

3- Контроллер

 public class Image
    {

      private IHostingEnvironment _hostingEnv;
      public Image(IHostingEnvironment hostingEnv)
      {
         _hostingEnv = hostingEnv;
      }

      [HttpPost]
      public async Task<IActionResult> UploadImage(UploadImage model, IFormFile ImageFile)
      {
        if (ModelState.IsValid)
         {
        var filename = ContentDispositionHeaderValue.Parse(ImageFile.ContentDisposition).FileName.Trim('"');
        var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images", ImageFile.FileName);
        using (System.IO.Stream stream = new FileStream(path, FileMode.Create))
         {
            await ImageFile.CopyToAsync(stream);
         }
          model.ImageFile = filename;
         _context.Add(model);
         _context.SaveChanges();
         }        

      return RedirectToAction("Index","Home");   
    }