Он работает на моем локальном компьютере, но не на IIS.
_Layout.cshtml:
Код: Выделить всё
@using Microsoft.AspNetCore.Identity
@using Memayo.ViewModels
@using Microsoft.AspNetCore.Http
@using System.Security.Claims
@inject SignInManager[url=~/css/site.css]
@* *@
@* *@
[img]~/images/logo.png[/img]
[/url]
[list]
@if (SignInManager.IsSignedIn(User))
{
@if (User.IsInRole("admin"))
{
[url=#]Friends[/url]
[url=#]
@if (user?.Avatar != null)
{
[img]@avatarUrl[/img]
}
else
{
}
[/url]
Profile
[*]Avatar
[*]
[*]Logout
[/list]
}
else
{
[*]
Register
[*]
Login
}
@RenderBody()
Privacy |
Terms
@await RenderSectionAsync("Scripts", required: false)
Код: Выделить всё
using CSharpAwsSesServiceHelper.EmailService;
using Memayo.Models;
using Memayo.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using System.Collections.Generic;
using Microsoft.Extensions.Hosting;
using Memayo.Repositories;
using Microsoft.AspNetCore.Http;
using System.IO;
using System.Linq;
using System;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;
namespace Memayo.Controllers
{
[Authorize(Roles = "user")]
public class MyProfileController : Controller
{
private readonly ILogger _logger;
private IWebHostEnvironment _env;
private SignInManager _signManager;
private UserManager _userManager;
private readonly IEmailService _emailService;
private readonly IUserRepository _userRepository;
private readonly IHttpContextAccessor _httpContextAccessor;
private string userId => _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
public MyProfileController(ILogger logger, IWebHostEnvironment env,
UserManager userManager, SignInManager signManager,
IEmailService emailService, IUserRepository userRepository,
IHttpContextAccessor httpContextAccessor)
{
_logger = logger;
_env = env;
_userManager = userManager;
_signManager = signManager;
_emailService = emailService;
_userRepository = userRepository;
_httpContextAccessor = httpContextAccessor;
}
public IActionResult Index()
{
return View();
}
public async Task Profile()
{
var user = await _userRepository.GetAsync(userId);
return View(user);
}
[HttpPost]
public async Task Profile(User user)
{
await _userRepository.UpdateProfileAsync(user);
TempData["message"] = "Profile Updated";
return RedirectToAction("Index", "Home");
}
[Authorize(Roles = "user")]
public async Task Avatar()
{
var user = await _userRepository.GetAsync(userId);
return View(user);
}
[HttpPost]
[Authorize(Roles = "user")]
public async Task Avatar(IFormFile avatar)
{
try
{
if (avatar == null)
{
_logger.LogError("Avatar is null");
return Json(new { success = false, error = "No file received" });
}
_logger.LogInformation($"Received file: {avatar.FileName}, Length: {avatar.Length}, ContentType: {avatar.ContentType}");
if (avatar.Length == 0)
{
TempData["messageError"] = "Please upload a valid image.";
return Json(new { success = false, error = "Empty file" });
}
// Check file type
var allowedExtensions = new[] { ".png", ".jpg", ".jpeg" };
var extension = Path.GetExtension(avatar.FileName).ToLower();
if (!allowedExtensions.Contains(extension))
{
TempData["messageError"] = "Only PNG and JPG images are allowed.";
return Json(new { success = false, error = "Invalid file type" });
}
// Delete old avatar if exists, get user
var user = await _userRepository.GetAsync(userId);
var uploadsDir = Path.Combine(_env.WebRootPath, "images", "uploads");
var filename = $"{Guid.NewGuid()}{extension}";
var oldAvatarPathLarge = Path.Combine(uploadsDir, "large", user.Avatar);
var oldAvatarPathSmall = Path.Combine(uploadsDir, "small", user.Avatar);
var newAvatarPathLarge = Path.Combine(uploadsDir, "large", filename);
var newAvatarPathSmall = Path.Combine(uploadsDir, "small", filename);
_logger.LogInformation($"Paths: New Large: {newAvatarPathLarge}, New Small: {newAvatarPathSmall}");
// Delete old avatar if exists
if (System.IO.File.Exists(oldAvatarPathLarge))
{
try
{
System.IO.File.Delete(oldAvatarPathLarge);
}
catch (Exception ex)
{
_logger.LogError($"Error deleting old large avatar: {ex.Message}");
}
}
if (System.IO.File.Exists(oldAvatarPathSmall))
{
try
{
System.IO.File.Delete(oldAvatarPathSmall);
}
catch (Exception ex)
{
_logger.LogError($"Error deleting old small avatar: {ex.Message}");
}
}
// Resize the image
using (var image = await Image.LoadAsync(avatar.OpenReadStream()))
{
_logger.LogInformation("Image loaded successfully");
var maxWidthLarge = 1000;
var maxHeightLarge = 1000;
var maxWidthSmall = 200;
var maxHeightSmall = 200;
var largeImage = image.Clone(ctx => ctx.Resize(new ResizeOptions
{
Size = new SixLabors.ImageSharp.Size(maxWidthLarge, maxHeightLarge),
Mode = ResizeMode.Max
}));
var smallImage = image.Clone(ctx => ctx.Resize(new ResizeOptions
{
Size = new SixLabors.ImageSharp.Size(maxWidthSmall, maxHeightSmall),
Mode = ResizeMode.Max
}));
_logger.LogInformation("Images resized");
try
{
if (extension == ".png")
{
await largeImage.SaveAsync(newAvatarPathLarge, new PngEncoder());
await smallImage.SaveAsync(newAvatarPathSmall, new PngEncoder());
}
else
{
await largeImage.SaveAsync(newAvatarPathLarge, new JpegEncoder());
await smallImage.SaveAsync(newAvatarPathSmall, new JpegEncoder());
}
_logger.LogInformation("Images saved successfully");
}
catch (Exception ex)
{
_logger.LogError($"Error saving images: {ex.Message}\nStack: {ex.StackTrace}");
throw;
}
}
// Update the user's avatar path in the database
user.Avatar = filename;
await _userRepository.UpdateAvatarAsync(user);
_logger.LogInformation("Database updated successfully");
TempData["message"] = "Avatar updated successfully.";
return Json(new { success = true });
}
catch (Exception ex)
{
_logger.LogError($"Avatar upload error: {ex.Message}\nStack: {ex.StackTrace}");
return Json(new { success = false, error = ex.Message });
}
}
}
}
Код: Выделить всё
@model Memayo.Models.User
@{
ViewData["Title"] = "Edit Avatar";
}
Edit Avatar
[h4]Current Avatar[/h4]
@if (!string.IsNullOrEmpty(Model.Avatar))
{
[img]/images/uploads/large/@Model.Avatar[/img]
}
else
{
No avatar uploaded. Please upload an avatar.
}
@if (TempData["message"] != null)
{
@TempData["message"]
}
@if (TempData["messageError"] != null)
{
@TempData["messageError"]
}
Select New Avatar
Allowed: .jpg, .png
Crop and Upload Avatar
Cancel
@section Scripts {
// Initialize state
const state = {
cropper: null,
uploadUrl: '@Url.Action("Avatar", "MyProfile")',
redirectUrl: '@Url.Action("Index", "Home")',
};
// Configuration object for Cropper
const cropperConfig = {
aspectRatio: 1,
viewMode: 1,
autoCropArea: 1,
};
// Handle file input change
function handleFileChange(event) {
const image = document.getElementById('preview');
const file = event.target.files[0];
if (!file) return;
const objectURL = URL.createObjectURL(file);
image.src = objectURL;
image.addEventListener('load', () => {
if (state.cropper) {
state.cropper.destroy();
}
// Initialize the cropper with config object
state.cropper = new Cropper(image, cropperConfig);
}, { once: true }); // Use once: true to prevent memory leaks
}
// Handle crop and upload
async function handleCropAndUpload() {
if (!state.cropper) {
alert('Please select an image to crop.');
return;
}
try {
const canvas = state.cropper.getCroppedCanvas({
width: 1000,
height: 1000
});
if (!canvas) {
throw new Error('Failed to generate canvas');
}
const blob = await new Promise((resolve) => {
canvas.toBlob(resolve, 'image/png', 0.9);
});
if (!blob) {
throw new Error('Failed to generate image blob');
}
const formData = new FormData();
formData.append('avatar', new File([blob], 'avatar.png', {
type: 'image/png'
}));
const response = await fetch(state.uploadUrl, {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
window.location.href = state.redirectUrl;
} else {
throw new Error(data.error || 'Upload failed');
}
} catch (error) {
console.error('Upload error:', error);
alert(`An error occurred: ${error.message}`);
}
}
// Add event listeners
document.getElementById('avatar').addEventListener('change', handleFileChange);
document.getElementById('cropButton').addEventListener('click', handleCropAndUpload);
}
Ошибка загрузки аватара: значение не может быть нулевым. (Параметр path3)
Эту ошибку я также получаю в инструментах браузера
Политика безопасности контента (CSP) предотвращает атаки с использованием межсайтовых сценариев
, блокируя встроенное выполнение сценариев и таблиц стилей.
Чтобы решить эту проблему, переместите все встроенные сценарии (например, onclick =[JS-код]) и
стили во внешние файлы.
внедрение элементов HTML-скрипта. Если вам абсолютно необходимо, вы можете
разрешить встроенные сценарии и стили:
добавив unsafe-inline в качестве источника в заголовок CSP, добавив хеш или
nonce встроенный скрипт в заголовок вашего CSP. 1 директива
Положение источника элемента директивы. Статус
script-src-elem Аватар: 119 заблокировано. Подробнее: Безопасность контента
Политика — встроенный код
Я спросил у Клода и Чата GPT 40 и o1. Они предложили мне добавить этот метатег, но это не помогло
и это может в любом случае вызывает проблемы с безопасностью.
У меня такое ощущение, что это связано с небезопасным заголовком CSP, но поиск в Google ничего не дал.
Как я могу это узнать? работаете на сервере?
Спасибо
Подробнее здесь: https://stackoverflow.com/questions/793 ... my-local-m