0

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; }
}
Nathan Fisher
  • 7,961
  • 3
  • 47
  • 68

0 Answers0