asp.net-mvcbytevirus-scanning

Cannot close stream until all bytes are written (VirusTotal API, Mvc)


This Question is different from

Sending file to VirusTotal with MVC

I am a student trying out another mini project where the user can upload a CSV file to the web server. But before I can create another program to execute the file, I would like to send the file to virustotal to have it check for the virus.

I tried but I got an error: "Cannot close stream until all bytes are written"

Here are my codes:

Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using VirusTotalNET;

namespace Testing_1.Controllers
{
public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Upload(HttpPostedFileBase file)
    {
        string filename = Server.MapPath("~/CSV/" + file.FileName);
        file.SaveAs(filename);
        FileInfo fi = new FileInfo(filename);
        VirusTotal vtObj = new VirusTotal("%API KEY");
        var resID = vtObj.ScanFile(fi).ToString();
        ViewBag.resID = resID;
        ViewBag.Path = filename;
        return View();
    }
  }
}

I got the error at this line: string resID = vtObj.ScanFile(file.FileName);

Index

@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype =   "multipart/form-data" }))
{
<input type="file" name="File" id="file"/>
<input type="submit" value="Upload" />
}

Upload

@{
ViewBag.Title = "Upload";
}

<h2>Uploaded: @ViewBag.Path : @ViewBag.resID</h2>

Stack Trace

[IOException: Cannot close stream until all bytes are written.]
   System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting) +609

[WebException: The request was aborted: The request was canceled.]
   VirusTotalNET.VirusTotal.GetResults(RestRequest request, Boolean applyHack) in d:\Source control\Github\VirusTotal.NET\VirusTotal.NET\VirusTotal.cs:687
   VirusTotalNET.VirusTotal.ScanFile(Stream fileStream, String filename) in d:\Source control\Github\VirusTotal.NET\VirusTotal.NET\VirusTotal.cs:191
   VirusTotalNET.VirusTotal.ScanFile(FileInfo file) in d:\Source control\Github\VirusTotal.NET\VirusTotal.NET\VirusTotal.cs:150
   C200_1.Controllers.HomeController.Upload(HttpPostedFileBase file) in C:\Users\FrezzeY\Desktop\C200\C200_1\Controllers\HomeController.cs:28
   lambda_method(Closure , ControllerBase , Object[] ) +103
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +30
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +197
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext     controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +46
   System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod() +37
   System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +24
   System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +43
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +68
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +69
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +230
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +27
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +27
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +68
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +42
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +124
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +27
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +29
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +27
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +48
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +21
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +32
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +26
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +40
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +21
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +24
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +27
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +48
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +21
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +29
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +23
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9744261
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Please help me Thank you


Solution

  • Saving the file to disk before scanning could be a security issue.

    You should scan it before trying to save it.

    Update your method.

    public ActionResult Upload(HttpPostedFileBase file) {
    
        string fileName = file.FileName
        var fileStream = new MemoryStream();
        file.InputStream.CopyTo(fileStream);
    
        var vtObj = new VirusTotal("%API KEY");
        var fileResults = vtObj.ScanFile(fileStream, fileName);
        var resId = fileResults.ScanId;
    
        //should do something based on message and then decide if you want to save the file
        var savePath = Server.MapPath("~/CSV/" + fileName);
        file.SaveAs(savePath);
    
        ViewBag.resID = resId;
        ViewBag.Path = savePath;
        return View();
    }