在我的ASP.NET核心3.1Web应用程序中,我允许用户上传存储在应用程序内部本地目录中的图像。虽然使用Azure上的blob存储可以提供更好的服务,但这个特定的项目要求将blob存储在本地,所以我必须使用它:
wwwroot/images/products/whatever_id/whatever_name.jpg和
wwwroot/images/companies/whatever_id/whatever_name.jpg当用户上传图像时,图像的处理由ImageSharp从SixLabors处理,其中图像被调整了几次大小,以便跨平台使用,并保存到由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>Edit(Controller)
[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();
}ProcessImages(Stream)
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(model)
public class Products : BaseEntity
{
public string Title { get; set; }
[NotMapped]
public IFormFileCollection ProductImages { get; set; }
}所以,问题仍然是,为什么我不能覆盖我的图像一旦我的应用程序生活在Azure?这是一个Azure安全问题,类似于ImageSharp库问题这样简单的问题,还是我的应用程序没有正确地执行此操作?
发布于 2021-02-26 13:48:13
这段代码看起来不正确。在ProcessImages中
null还给我。@LazZiya在缓存方面是正确的。由于您再次重复使用相同的名称,浏览器只需请求相同的缓存图像。如果在例如v=[PRODUCTRECORD_LASTWRITETIME]中添加任何querystring参数,就会得到新的图像。
为了简单起见,我建议您简单地上传源映像,并使用ImageSharp.Web中间件为您调整大小的映像提供服务。
这将自动处理源映像更改,并减少存储开销。您可以在服务器上托管源映像,并在blob存储中缓存结果。
请求变得非常简单
https://PATH_TO_IMAGE?with=[NUMBER]
https://stackoverflow.com/questions/66320283
复制相似问题