I am using NPOI to save files to an .xls format.
I would like to save an empty file for now that a user has a dialog box and is prompted to save it locally.
The problem I have is I cannot set the Response fields, because
The name 'Response' does not exist in the current context.
This is the class I want to use:
https://learn.microsoft.com/en-us/dotnet/api/system.web.httpresponse?view=netframework-4.8
//Load all documents sorted by DocNumber and export them
var documents = await _ctx.Db.Documents
.AsNoTracking()
.OrderByDescending(d => d.Number)
.ToListAsync();
var workbook = new HSSFWorkbook();
var sheet = workbook.CreateSheet("Invoicing_Docs");
using (var exportData = new MemoryStream())
{
workbook.Write(exportData);
string saveAsFileName = string.Format("Invoicing_Docs-{0:d}.xls", DateTime.UtcNow).Replace("/", "-");
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", saveAsFileName));
Response.Clear();
Response.BinaryWrite(exportData.GetBuffer());
Response.End();
}
I have installed System.Web in the project.
When I ctrl + . on Response I have 3 choices:
Install package "IdentityMode",
Install package "Selenium.WebDriver"
Install package "Swashbuckle.AspNetCore.Swagger"
Also this is the article, I am following:
https://steemit.com/utopian-io/#haig/how-to-create-excel-spreadsheets-using-npoi
I don't need any of those. What am I doing wrong?
I found out what I need to do.
I was not using the controller I was writing a service that is called in the controller.
All I had to do is inject Response in the Method of the service.
Related
I have a project ASP.NET Core 2.0 MVC running on IIS.
Want to Export some information from data grid to Excel and save it from web page to the desktop of current user.
string fileName = "SN-export-" + DateTime.Now + ".xlsx";
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
fileName = rgx.Replace(fileName, ".");
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string fileName2 = Path.Combine(path, fileName);
FileInfo excelFile = new FileInfo(fileName2);
excel.SaveAs(excelFile);
This works perfect local at Visual Studio, but not after publishing at IIS.
Using simple path string path = #"C:\WINDOWS\TEMP"; It will save this export file at the server temp folder, but not current web page user.
How to get this?
ASP.NET MVC is framework for a web application. So you have fronted and backend parts. This code will executed on the server side of your application. Even if you use Razor pages, they also generated at the backend. So there are several ways to save data on the computer:
use js to iterate data and save it, but I'm not sure that saving to excel with js is easy;
send desired data to backend, save it to excel and then return to the client.
For a second way you can use next code:
[Route("api/[controller]")]
public class DownloadController : Controller {
//GET api/download/12345abc
[HttpGet("{id}"]
public async Task<IActionResult> Download(YourData data) {
Stream stream = await {{__get_stream_based_on_your_data__}}
if(stream == null)
return NotFound();
return File(stream, "application/octet-stream"); // returns a FileStreamResult
}
}
And because of security reasons you can save data only to downloads directory.
I am not sure what is happening here.
When I run my web application locally and click a button to download a file, the file is downloaded fine and Response header as you can see in the attached screenshot where it says local.
But when I publish the application to azure web app. Somehow the download button stops working. I checked the Response Header and you can see the difference.
What would cause this problem? The code is the same? Is there any settings that I should be setting in azure web app in azure portal?
Updated to add code
I have debugged remotely to figure out what is going on as #Amor suggested.
It is so strange that When I debug on my local machine first ExportTo action gets hit which prepares the TempData then Download action gets called once the first action completed with ajax call.
However, this is not the case when I debug remotely. Somehow the ExportTo action never gets called. It directly calls the Download action. As a result the TempData null checking is always null.
But why? Why on earth and how that is possible? Is there something cached somewhere?
I have wiped the content of web application on the remote and re-publish evertyhing to ensure everything is updated. But still no success.
here is the code:
[HttpPost]
public virtual ActionResult ExportTo(SearchVm searchVm)
{
var data = _companyService.GetCompanieBySearchTerm(searchVm).Take(150).ToList();
string handle = Guid.NewGuid().ToString();
TempData[handle] = data;
var fileName = $"C-{handle}.xlsx";
var locationUrl = Url.Action("Download", new { fileGuid = handle, fileName });
var downloadUrl = Url.Action("Download");
return Json(new { success = true, locationUrl, guid = handle, downloadUrl }, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult Download(string fileGuid, string fileName)
{
if (TempData[fileGuid] != null)
{
var fileNameSafe = $"C-{fileGuid}.xlsx";
var data = TempData[fileGuid] as List<Company>;
using (MemoryStream ms = new MemoryStream())
{
GridViewExtension.WriteXlsx(GetGridSettings(fileNameSafe), data, ms);
MVCxSpreadsheet mySpreadsheet = new MVCxSpreadsheet();
ms.Position = 0;
mySpreadsheet.Open("myDoc", DocumentFormat.Xlsx, () =>
{
return ms;
});
mySpreadsheet.Document.Worksheets.Insert(0);
var image = Server.MapPath("~/images/logo.png");
var worksheet = mySpreadsheet.Document.Worksheets[0];
worksheet.Name = "Logo";
worksheet.Pictures.AddPicture(image, worksheet.Cells[0, 0]);
byte[] result = mySpreadsheet.SaveCopy(DocumentFormat.Xlsx);
DocumentManager.CloseDocument("myDoc");
Response.Clear();
//Response.AppendHeader("Set-Cookie", "fileDownload=true; path=/");
Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", $"attachment; filename={fileNameSafe}");
Response.BinaryWrite(result);
Response.End();
}
}
return new EmptyResult();
}
here is the javascript:
var exportData = function (urlExport) {
console.log('Export to link in searchController: ' + urlExport);
ExportButton.SetEnabled(false);
var objData = new Object();
var filterData = companyFilterData(objData);
console.log(filterData);
$.post(urlExport, filterData)
.done(function (data) {
console.log(data.locationUrl);
window.location.href = data.locationUrl;
});
};
When Export button is clicked exportData function is called:
var exportToLink = '#Url.Action("ExportTo")';
console.log('Export to link in index: '+exportToLink);
SearchController.exportData(exportToLink);
As I mentioned that this code works perfectly on the local machine. something weird is happening on azure webapp that ExportTo action breakpoint is never gets hit.
I am not sure what else I could change to get the ExportTo action hit?
Based on the Response Header of Azure Web App, we find that the value of Content-Length is 0. It means that no data has been sent from web app server side.
In ASP.NET MVC, we can response file using following ways.
The first way, send the file which hosted on server. For this way, please check whether the excel file has been uploaded to Azure Web App. You could use Kudu or FTP to the folder to check whether the file is exist.
string fileLocation = Server.MapPath("~/Content/myfile.xlsx");
string contentType = System.Net.Mime.MediaTypeNames.Application.Octet;
string fileName = "file.xlsx";
return File(fileLocation, contentType, fileName);
The second way, we can read the file from any location(database, server or azure storage) and send the file content to client side. For this way, please check whether the file has been read successfully. You can remote debug your azure web app to check whether the file content hasn't been read in the right way.
byte[] fileContent = GetFileContent();
string contentType = System.Net.Mime.MediaTypeNames.Application.Octet;
string fileName = "file.xlsx";
return File(fileContent, contentType, fileName);
5/27/2017 Update
Somehow the ExportTo action never gets called. It directly calls the Download action. As a result the TempData null checking is always null.
How many instances does your Web App assigned? If your Web App have multi instances, the ExportTo request is handled by one instance and the Download request is handled by another instance. Since the TempData is store in memory of dedicated instance, it can't be got from another instance. According to the remote debug document. I find out the reason why the ExportTo action never gets called.
If you do have multiple web server instances, when you attach to the debugger you'll get a random instance, and you have no way to ensure that subsequent browser requests will go to that instance.
To solve this issue, I suggest you response the data directly from the ExportTo action or save the temp data in Azure blob storage which can't be accessed from multi instances.
I need to set create a page on which i have button and on clicking, it should redirect to a registration page and then download a pdf file. so i created a document type in Umbraco which have a file Upload field and i uploaded one file through it. On its template i have added a macro which have a partial view for the registration page. After completing registration, this pdf file should download automatically.
My problem is, the file i uploaded is not showing in the Media library. but the Url is as follows: /media/1051/filname.pdf .
am getting this url in controller. but couldn't get the file usinng its id.
[HttpPost]
public HttpResponseMessage DownloadFile([FromBody] DownloadEBookViewModel model)
{
int id = Convert.ToInt32(model.Url.Split('/')[2]);
var media = Umbraco.Media(id).Url;
if (!File.Exists(media))
throw new HttpResponseException(HttpStatusCode.NotFound);
HttpResponseMessage Response = new HttpResponseMessage(HttpStatusCode.OK);
byte[] fileData = File.ReadAllBytes(media);
if (fileData == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
Response.Content = new ByteArrayContent(fileData);
Response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return Response;
}
Someone please help. thank you
When working with the Umbraco helper in code behind, I would advise to use the typed variants for getting items
var media = Umbraco.TypedMedia(id).Url;
This will give you a strongly typed model with intellisense
To get the physical file from the media object you'll probably want to call
byte[] fileData = File.ReadAllBytes(media.getPropertyValue("umbracoFile"));
instead of:
byte[] fileData = File.ReadAllBytes(media);
(code is untested)
I have written some Asp.Net MVC code that returns an Html file FileResult.
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(htmlReport);
writer.Flush();
stream.Position = 0;
return File(stream, "text/html", fileName);
Using my local environment the HTML file looks fine when opened but after deploying to the server and downloading the same file some unwanted  characters can be seen. How could the difference in server environments be affecting a file which is downloaded to the users pc?
You need to specify the file encoding. You are most likely using UTF8, but other formats are available.
var writer = new StreamWriter(stream, System.Text.Encoding.UTF8);
Why use the StreamWriter at all?
return Content(htmlReport, "text/html", System.Text.Encoding.UTF8);
Or if you want to be using File as your return result try:
byte[] bArray = System.Text.Encoding.UTF8.GetBytes(htmlReport);
return File(bArray, "text/html", fileName);
I have an ASP.NET MVC2 application in development and I am having problems rendering a .pdf file from our production server.
On my Visual Studio 2010 integrated development server everything works fine, but after I publish the application to the production server, it breaks. It does not throw any exceptions or errors of any kind, it simply does not show the file.
Here's my function for displaying the PDF document:
public static void PrintExt(byte[] FileToShow, String TempFileName,
String Extension)
{
String ReportPath = Path.GetTempFileName() + '.' + Extension;
BinaryWriter bwriter =
new BinaryWriter(System.IO.File.Open(ReportPath, FileMode.Create));
bwriter.Write(FileToShow);
bwriter.Close();
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = ReportPath;
p.StartInfo.UseShellExecute = true;
p.Start();
}
My production server is running Windows Server 2008 and IIS 7.
You cannot expect opening the default program associated with PDF file browsing on the server. Try returning the file into the response stream which will effectively open it on the client machine:
public ActionResult ShowPdf()
{
byte[] fileToShow = FetchPdfFile();
return File(fileToShow, "application/pdf", "report.pdf");
}
And now navigate to /somecontroller/showPdf. If you want the PDF opening inside the browser instead of showing the download dialog you may try adding the following to the controller action before returning:
Response.AddHeader("Content-Disposition", "attachment; filename=report.pdf");
i suggest you use ASP.NET MVC FileResult Class to display the PDF.
see http://msdn.microsoft.com/en-us/library/system.web.mvc.fileresult.aspx
your code open`s the PDF on the webserver.
Here's how I did it.
public ActionResult PrintPDF(byte[] FileToShow, String TempFileName, String Extension)
{
String ReportPath = Path.GetTempFileName() + '.' + Extension;
BinaryWriter bwriter = new BinaryWriter(System.IO.File.Open(ReportPath, FileMode.Create));
bwriter.Write(FileToShow);
bwriter.Close();
return base.File(FileToShow, "application/pdf");
}
Thank you all for your efforts. Solution I used is the most similar to the Darin's one (almost the same, but his is prettier :D), so I will accept his solution.
Vote up for all of you folks (both for answers and comments)
Thanks