在我的 ASP.NET Core 3.1 Web 应用程序中,我允许用户上传存储在应用程序本身的本地目录中的图像。虽然,使用 Azure 上的 blob 存储可以更好地实现这一点,但这个特定项目要求将它们存储在本地,所以我必须使用它:
wwwroot/images/products/whatever_id/whatever_name.jpg
和
wwwroot/images/companies/whatever_id/whatever_name.jpg
当用户上传图像时,图像的处理由 SixLabors 的 ImageSharp 处理,其中图像被调整几次以供跨平台使用,并保存到由 Id 分隔的相对目录中。
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
问题
我面临的问题是,虽然当我在本地测试我的应用程序时这个过程有效,但当我将我的应用程序部署到 Azure 并且没有报告任何类型的错误时它不起作用。当我试图弄清楚发生了什么时,这让我感到兴奋和干燥。
假设
由于这个问题的性质和这些图像的位置,我只能假设它是天蓝色的,出于安全原因防止覆盖目录中的图像,或者它可能是 ImageSharp 库本身。
重要的是要注意,当目录不存在时,实际创建产品和添加图像,因此,一个新产品可以完美地工作。只有当你试图覆盖它不起作用的图像时。
这是我的代码,我删除了所有非必要元素,留下了图像处理特定的代码。
编辑视图)
@model Products
<form asp-action="Edit" asp-controller="Products" method="POST" enctype="multipart/form-data">
<div class="card m-4">
<div class="card-header">
<h3 class="card-title">Add Product</h3>
</div>
<div class="card-body">
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Product Images</label>
<kendo-upload name="ProductImages" multiple="true" show-file-list="true">
</kendo-upload>
</div>
</div>
</div>
<div class="row">
<div class="col">
<button type="submit" class="btn btn-purple">Submit</button>
</div>
</div>
</div>
</div>
</div>
</form>
编辑(控制器)
[HttpPost]
public IActionResult Edit(Products product)
{
if (ModelState.IsValid && product != null)
{
try
{
//Process the Images
if (product.ProductImages != null)
{
ProcessImages(product, product.Id);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return RedirectToAction("Index");
}
return View();
}
处理图像(流)
private readonly int[] sizeArray = new int[] { 700, 350, 150 };
public Stream ProcessImages(Products model, int? id)
{
try
{
//Get the images and define the directory structure
var images = model.ProductImages;
var root = _env.WebRootPath;
var folderName = Path.Combine(root, "images", "products", id.ToString());
//If the ID Directory doesn't exist, create it first.
if (!Directory.Exists(folderName))
{
Directory.CreateDirectory(folderName);
}
//Interate over the images and process them
foreach (var item in images)
{
foreach (var imageSize in sizeArray)
{
string imageSizeName = "image" + imageSize + ".jpg";
string fullPath = Path.Combine(folderName, imageSizeName);
//Create the stream and process the image
using FileStream fileStream = new FileStream(fullPath, FileMode.Create);
try
{
Stream inStream = item.OpenReadStream();
using Image image = Image.Load(inStream);
int width = imageSize;
int height = 0;
var clone = image.Clone(i => i.Resize(width, height));
clone.SaveAsJpeg(fileStream);
inStream.Position = 0;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return (null);
}
如您所见,有一个大小数组,其中定义了我们需要的大小,然后循环处理。我们创建文件名并保存为 jpg。高度设置为 0,以便在定义宽度然后重置流时自动设置它。
Products.cs(模型)
public class Products : BaseEntity
{
public string Title { get; set; }
[NotMapped]
public IFormFileCollection ProductImages { get; set; }
}
所以,问题仍然存在,为什么我的应用程序在 Azure 中运行后不能覆盖我的图像?是 Azure 安全问题,还是 ImageSharp 库问题之类的简单问题,还是我的应用程序没有正确执行此操作?