I have a macro enabled Excel spreadsheet (*.xlsm
) that is being uploaded to an ASP.NET MVC controller. The controller method has validation in it that does not allow macro enabled excel spreadsheets.
What I have done in the controller is to check the mimetype and filename so see if it is a *.xlsm
file and converted it to a standard Excel spreadsheet (*.xlsx
) file, and then passed it to the regular validation and processing of the file.
What I want to be able move that conversion functionality to an ActionFilterAttribute
or some OWIN middleware, but I keep hitting a roadblock of the Request.Files
contains the original file when the controller action is executed.
I am using Aspose.Cells to convert the file from *.xlsm
to *.xlsx
without an issue. The issue is getting the converted file back into the request so that it is transparent to the controller action.
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
var files = actionContext?.HttpContext.Request.Files;
if (files is null)
{
return;
}
var newFiles = new List<FormsPostedFile>();
foreach (string file in files)
{
var postedFile = files[file];
if (postedFile == null || postedFile.ContentLength == 0)
{
continue;
}
using (var memoryStream = new MemoryStream())
{
postedFile.InputStream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var workbook = new Workbook(memoryStream);
workbook.RemoveMacro();
workbook.Save(memoryStream, SaveFormat.Xlsx);
memoryStream.Seek(0, SeekOrigin.Begin);
context.Request.Body = memoryStream;
//context.Request.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
context.Environment.Keys.Select(x => { Debug.Print(x); return x; }).ToList();
var filename = HttpContext.Current.Request.Files[0].FileName.Replace(".xlsm", ".xlsx");
}
//var workbook = new Workbook(stream);
//workbook.RemoveMacro();
//var filestream = new FileStream(Path.Combine(Path.GetTempPath(), $"{postedFile.FileName.Replace(".xlsm", ".xlsx")}"), FileMode.OpenOrCreate);
//workbook.Save(filestream, SaveFormat.Xlsx);
//files.Add(filestream);
//newFiles.Add(new FormsPostedFile(postedFile.FileName.Replace(".xlsm", ".xlsx"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filestream));
postedFile = new FormsPostedFile(postedFile.FileName.Replace(".xlsm", ".xlsx"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filestream);
// modify the postedFile Here
}
}
internal class FormsPostedFile : HttpPostedFileBase
{
private readonly Stream _inputStream;
public FormsPostedFile(string filename, string contentType, Stream inputStream)
{
this.FileName = filename;
this.ContentType = contentType;
_inputStream = inputStream;
ContentLength = (int)inputStream.Length;
}
public override string ContentType { get; }
public override string FileName { get; }
public override Stream InputStream => _inputStream;
public override int ContentLength { get; }
}