c# - 为 asp.net mvc 应用程序处理 Stream 对象的问题?
问题描述
我有具有文件上传功能的 asp.net mvc 应用程序。在上传文件时,我在将上传的内容移动到数据库和文件系统位置之前对其进行了一些验证。
这是我的代码:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddImage([Bind(Include = "image,ImageName,ImageType,CountryId,Keyword,Source,Copyright,Description")] CreateImageViewModel model)
{
if (!this.ModelState.IsValid)
{
return View("Images");
}
if (model != null && model.image.ContentType.Contains(Constants.Image) && !ValidateUploadedImageContent(model.image, model.image.FileName))
{
var dto = new ImageDTO();
model.FilePath = model.image.FileName;
dto.ImageFile = model.image;
dto.Name = model.ImageName;
dto.FilePath = model.image.FileName;
dto.FileType = Path.GetExtension(model.FilePath);
dto.ImageType = model.ImageType;
dto.CountryId = model.CountryId;
dto.Keyword = model.Keyword;
dto.Source = model.Source;
dto.Copyright = model.Copyright;
dto.Description = model.Description;
dto.CreatedBy = UserDto.emailId;
try
{
_imageService.SaveImage(dto);
}
catch (Exception ex)
{
if (ex.Message.Equals(Constants.InvalidImageType))
return GetSafeRedirect(Url.Action("AddImage", model) + "#onload-errors");
throw ex;
}
return RedirectToAction(Constants.Actions.Images.ToString());
}
else
{
return GetSafeRedirect(Url.Action("AddImage", model) + "#onload-errors");
}
}
private bool ValidateUploadedImageContent(HttpPostedFileBase uploadedFile, string imageFileName)
{
if (Path.GetExtension(imageFileName).Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
if (uploadedFile.ContentLength > 0)
{
byte[] data;
//using (Stream inputStream = uploadedFile.InputStream)
//{
Stream inputStream = uploadedFile.InputStream;
var memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
data = memoryStream.ToArray();
//}
var parsedData = Encoding.UTF8.GetString(data, 0, data.Length).TrimEnd('\0');
var result = parsedData.ContainsAny(Constants.InsecureStrings, StringComparison.CurrentCultureIgnoreCase);
return result;
}
}
return false;
}
在上面的方法中:ValidateUploadedImageContent(),我尝试在 using 语句的帮助下处理流对象,但我发现如果我在方法中保留以下代码:ValidateUploadedImageContent(),那么在这种情况下,在验证过程之后,我在调试时发现 ContentLength 属性设置为 0 值,最后损坏的图像保存在文件系统位置。
更新 :
private bool ValidateUploadedImageContent(HttpPostedFileBase uploadedFile, string imageFileName)
{
if (Path.GetExtension(imageFileName).Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
if (uploadedFile.ContentLength > 0)
{
byte[] data;
using (Stream inputStream = uploadedFile.InputStream)
{
Stream inputStream = uploadedFile.InputStream;
var memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
data = memoryStream.ToArray();
}
var parsedData = Encoding.UTF8.GetString(data, 0, data.Length).TrimEnd('\0');
var result = parsedData.ContainsAny(Constants.InsecureStrings, StringComparison.CurrentCultureIgnoreCase);
return result;
}
}
return false;
}
谁能帮我知道如何解决这个问题?
解决方案
首先解决你的问题,我现在明白的是,调用后ValidateUploadedImageContent
的图像流是无效的。
这是因为从HttpPostedFileBase获得的流是“只读顺序(不可搜索)”,如本 SO answer中所述。这解释了为什么流的 ContentLength 为 0 - 流已被验证调用消耗。
如果您对 ImageDTO 类具有灵活性,那么修改验证方法以使其返回图像字节将是一种解决方法。
例如,
// on success, buffer contains the image data. Otherwise it is null.
private bool ValidateUploadedImageContent(
out byte[] buffer,
HttpPostedFileBase uploadedFile,
string imageFileName)
{
buffer = null;
if (Path.GetExtension(imageFileName).Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
if (uploadedFile.ContentLength > 0)
{
var reader = new BinaryReader(inputStream);
buffer = reader.ReadBytes((int)uploadedFile.ContentLength);
var parsedData = Encoding.UTF8.GetString(buffer, 0, buffer.Length).TrimEnd('\0');
return parsedData.ContainsAny(Constants.InsecureStrings, StringComparison.CurrentCultureIgnoreCase);
}
}
return false;
}
我使用 BinaryReader 来简化代码。
然后回到调用方法,
byte[] imageBuffer = null;
if (model != null && model.image.ContentType.Contains(Constants.Image)
&& !ValidateUploadedImageContent(out imageBuffer, model.image, model.image.FileName)) {
var dto = new ImageDTO();
using(var imageStream = new MemoryStream(imageBuffer)) {
// pass along imageStream to your ImageDTO and save.
}
}
同样,希望您对 ImageDTO 类有一些灵活性。
推荐阅读
- github - 如何获得 github gist 的见解(流量等)?
- angular - 角度 cdk 拖放在延迟加载中不起作用
- html - 可以使徽标图像具有响应性,但在 div 中不起作用
- powershell - 如何使用 Get-WmiObject 获取 Windows“已安装更新视图”的完整列表,因为它出现在控制面板中
- python - 我必须覆盖整数 __add__ 方法以支持整数和对象的加法吗?
- python - 重新绘制 2 个 pyplot 图表而不重新绘制新图表
- python - 如何使用 RSA 加密对超过 53 个字节的消息进行加密?
- bash - 如何从目录中创建的最新目录中复制文件?
- node.js - 为单个请求捕获多个路由
- docker - 在 docker 中运行 Localstack 时转发请求时出错