Im making a controller that is to return a file based on a model in a database but im having issues with getting a prompt to download the file. The controller looks like this atm:
public ActionResult CreateFile(string ID)
{
int id = int.Parse(licneseFileID);
File_Type file = db.Files.FirstOrDefault(li => li.ID == id);
string fileName = Path.Combine(Server.MapPath(@"~\App_Data\TempData"), file.NAME.Replace(" ", string.Empty) ".lic");
WriteFile(fileName) //Here the file is created and its content is writen based on the data model
ProcessStartInfo startInfo = new ProcessStartInfo(Server.MapPath(@"~\rlmsign12.exe"), fileName);
Process.Start(startInfo); //im runnig a 3rd party .exe to sign the file for licensing
try
{
Debug.WriteLine("Works?");
return File(fileName, MimeMapping.GetMimeMapping(fileName), System.IO.Path.GetFileName(fileName)); //The problem is here. Getting no download when it runs. filename is a full path.
}
catch (Exception)
{
Debug.WriteLine("Fail");
throw;
}
finally
{
//send file to blob here if we are going to be using a blob.
//System.IO.File.Delete(fileName); //Delete file from application to avoid filling it upp with files. Send to local storage? Extra backup
}
}
To explain it.
Get the file from the database
Save it path to "fileName".
Run it through a method that creates the file in a sub folder in App_Data and then writes the files content. Sign the file with 3rd party software.
Send the file to user. <-This is the problem.
Delete the file
So the problem is when i run the controller im getting no download prompt thorugh the client. I know that the return statement does not fail since it does not throw an exception. Ive checked downloads and there is nothing.
I tried turning of chrome security.
Ive tried to return the file as a byte array. I have also tried some diffrent content types.
Am i missing something obvious like a attribute to the method?
The method is currently run directly by the index metod in the controller class (with hard coded argument) for testing purposes.
Edit: IE it is called when the page is loaded.
public ActionResult Index()
{
CreateFile("2");
return View(db.LICENSE_FILES.ToList());
}
Comment from Peter B brought upp something pretty obvious. Im calling the method before the view even is returned. Legacy from when i was writing it.
Edit 2: Tried calling the action with Jquery:
<script>
function call()
{
$.ajax
({
url: '/LicenseFiles/CreateFile',
data: { licneseFileID: "2" }
})
.done(function ()
{
alert('test');
})
}
I can se the action get called in the network tab but i am getting no prompt to save the file and nothing gets downloaded.
CodePudding user response:
Your 1st attempt (calling CreateFile from Index) isn't going to work, and it looks like you already understand why. Instead, doing a redirect to CreateFile would work, but then the file download will be the ultimate response of the call that was made to Index, and no new View will be shown.
The 2nd attempt doesn't work because a download only "happens" if the request was done by the browser window. When using $.ajax it's a XMLHttpRequest object that makes the request, it will receive the data and then it is up to you to extract the data and e.g. turn it into a Blob for download - not really easy or convenient.
A much easier solution would be to do this:
window.location = "/CreateFile/2";
or possibly (depending on your routing):
window.location = "/CreateFile?id=2";
