Как сохранить существующее изображение, если не выбрано новое изображение? - PullRequest
1 голос
/ 26 мая 2020

Я знаю, что есть похожие вопросы. Но я провела целый день и не смогла решить свою проблему, потому что я совершенно нуб. Поэтому я был бы признателен, если бы кто-нибудь предоставил конкретное решение c для моего проекта ASP. Net Core .

Если вам нужна дополнительная информация, просто спросите.

Спасибо.


Итак, мой проект о Директорах:

public class Director
{
    public Director()
    {
        Movies = new List<Movie>();
    }
    public int DirectorId { get; set; }
    [Required]
    public string Name { get; set; }
    public string Country { get; set; }
    public string Bio { get; set; }
    public List<Movie> Movies { get; set; }
    public string PhotoURL { get; set; } // This field holds only the name of the photo, Not its URL.
}

Мой проект сохраняет изображения в «wwwroot/uploads». У каждого режиссера есть образ. Я могу выбрать новый образ на жестком диске для каждого директора.

Проблема:

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


Edit.cshtl.cs

public class EditModel : PageModel
{
    private readonly Context _context;
    private readonly IWebHostEnvironment hostingEnvironment;

    public EditModel(Context context, IWebHostEnvironment environment)
    {
        _context = context;
        this.hostingEnvironment = environment;
    }

    [BindProperty]
    public Director Director { get; set; }
    [BindProperty]
    public IFormFile Image { set; get; }
    public async Task<IActionResult> OnGetAsync(int? directorId)
    {
        if (directorId == null)
        {
            return NotFound();
        }

        Director = await _context.Director.FirstOrDefaultAsync(m => m.DirectorId == directorId);

        if (Director == null)
        {
            return NotFound();
        }
        return Page();
    }

    // To protect from overposting attacks, enable the specific properties you want to bind to, for
    // more details, see https://aka.ms/RazorPagesCRUD.
    public async Task<IActionResult> OnPostAsync(int? directorId)
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        if (this.Image != null)
        {
            var fileName = GetUniqueName(this.Image.FileName);
            var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
            var filePath = Path.Combine(uploads, fileName);
            this.Image.CopyTo(new FileStream(filePath, FileMode.Create));
            this.Director.PhotoURL = fileName; // Set the file name
        }

        _context.Attach(Director).State = EntityState.Modified;
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!DirectorExists(Director.DirectorId))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return RedirectToPage("./Index");
    }

    private bool DirectorExists(int id)
    {
        return _context.Director.Any(e => e.DirectorId == id);
    }
    private string GetUniqueName(string fileName)
    {
        fileName = Path.GetFileName(fileName);
        return Path.GetFileNameWithoutExtension(fileName)
               + "_" + Guid.NewGuid().ToString().Substring(0, 4)
               + Path.GetExtension(fileName);
    }



}

Edit.cs html

<form method="post" enctype="multipart/form-data">
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>

        <input type="hidden" asp-for="Director.DirectorId" />



        <div class="form-group">
            <label asp-for="Director.Name" class="control-label"></label>
            <input asp-for="Director.Name" class="form-control" />
            <span asp-validation-for="Director.Name" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Director.Country" class="control-label"></label>
            <input asp-for="Director.Country" class="form-control" />
            <span asp-validation-for="Director.Country" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Director.Bio" class="control-label"></label>
            <input asp-for="Director.Bio" class="form-control" />
            <span asp-validation-for="Director.Bio" class="text-danger"></span>
        </div>



        <div>
            <img id="blah" src="~/uploads/@Model.Director.PhotoURL" />
        </div>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

        <div class="form-group" runat="server">
            <label asp-for="Director.PhotoURL" class="control-label"></label>
            <input type="file" asp-for="Image" class="form-control" id="imgInp" value="~/uploads/@Model.Director.PhotoURL" />
            <span asp-validation-for="Director.PhotoURL" class="text-danger"></span>
        </div>

        <div class="form-group">
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>

    </form>

site. js:

function readURL(input) {
if (input.files && input.files[0]) {

    var reader = new FileReader();


    reader.onload = function (e) {
        $('#blah').attr('src', e.target.result);
    }

    reader.readAsDataURL(input.files[0]); // convert to base64 string
    }
}

$("#imgInp").change(function () {
    if ($('#imgInp').get(0).files.length !== 0) {

        readURL(this);
    }
});

Редактировать страницу:

If I press save without selecting a new image, It will delete the existing image.

Ответы [ 2 ]

1 голос
/ 26 мая 2020

Проще всего использовать предложение else в вашем вызове OnPostAsyn c здесь: if (this.Image != null)

Поскольку вы устанавливаете контекст в измененный и выполняете обновление, вы пишете нуль к изображению. С помощью else вы можете сделать что-то вроде этого:

else { this.Director.PhotoURL = LastImage; }

Что касается того, как вы получаете значение для LastImage, самый простой способ - получить его через запрос linq, используя DirectorId, который был передан (точно так же, как вы получили объект Director чуть выше).

1 голос
/ 26 мая 2020

Самый простой способ изменить ваш код - это получить доступ к базе данных и установить путь к исходному изображению, если новый путь к изображению равен нулю. Однако у этого есть недостаток, связанный с дополнительным вызовом базы данных:

if (this.Image != null)
{
    ...
}

else
{
    Director.PhotoURL = (await _context.Director.FirstOrDefaultAsync(m => m.DirectorId == directorId))?PhotoURL;
}

Другой вариант - сохранить где-нибудь исходный путь изображения, когда вы извлекаете его из базы данных, а затем использовать его, если путь нового изображения равен нулю . Это не потребует дополнительного получения. Вы можете сделать что-то вроде:

[BindProperty]
public string OriginalImage { set; get; }

...

OriginalImage = Director.PhotoURL

...

<input type="hidden" asp-for="OriginalImage"/>

...

if (this.Image != null)
{
    ...
}

else
{
    Director.PhotoURL = OriginalImage;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...