I want to delete a folder and its content before returning some data from the browser.
I am using ASP .NET MVC 5 and just javascript with some DevExpress components.
The method should return a HttpResponseMessage, which is the excel file. The file is created in a temp folder and after that I want to delete it.
I get always an "UnauthorizedAccessException" exception.
Any idea how the logic flow should be to return the file and delete it?
I was thinking on calling a new method after finishing the ExportExcelChart but maybe there is a better way to achieve the expected result.
How
JS (browser)
function SaveChart(s, e) {
//debugger;
if (e.item.name === 'mnuSaveToDisk') {
averageChart.printOptions.landscape = true;
averageChart.printOptions.SetSizeMode('Stretch');
averageChart.SaveToDisk('pdf', "average curves");
} else if (e.item.name == 'mnExportChart') {
ChartLoadingPanel.Show();
#*$.get('#Url.Action("ExportExcelChart", "Mindboard")', {}, null);*#
window.location = '#Url.Action("ExportExcelChart", "Mindboard")';
ChartLoadingPanel.Hide();
}
}
Controller
public HttpResponseMessage ExportExcelChart()
{
try
{
// create excel file
String tmpRandomFolderName = DataService.RandomString(20);
string tmpFolderPath = Path.Combine(Server.MapPath("~/App_Data"), "TEMP", tmpRandomFolderName);
string tmpOriginFile = Server.MapPath("~/App_Data") + "/ExportChartAverage.xlsx";
string tmpNewFile = tmpFolderPath + "/ExportChartAverage.xlsx";
if (!Directory.Exists(tmpFolderPath))
Directory.CreateDirectory(tmpFolderPath);
System.IO.File.Copy(tmpOriginFile, tmpNewFile);
// open excel file
FileInfo tmpExcelFile = new FileInfo(tmpNewFile);
ExcelPackage pck = new ExcelPackage(tmpExcelFile);
var ws = pck.Workbook.Worksheets[1];
// do stuff...
pck.SaveAs(Response.OutputStream);
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=ExportChartAverage.xlsx");
if (Directory.Exists(tmpFolderPath))
{
if (System.IO.File.Exists(tmpNewFile))
System.IO.File.Delete(tmpNewFile);
Directory.Delete(tmpFolderPath, true);
}
var response = new HttpResponseMessage(HttpStatusCode.OK);
return response;
}
catch (IOException ex)
{
var response = new HttpResponseMessage(HttpStatusCode.NotFound);
response.Content = new StringContent(ex.Message);
return response;
//throw ex;
}
catch (UnauthorizedAccessException ex)
{
var response = new HttpResponseMessage(HttpStatusCode.NotFound);
response.Content = new StringContent(ex.Message);
return response;
//throw ex;
}
catch (Exception)
{
throw;
}
}
Related
I have an api which return below response, which contain the excel file content.
So now I need to convert them into excel file and download for the user.
Here is the api function
[HttpGet]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> DownloadLoadedTrnFile(string S3Path)
{
try
{
string bucket = "taurus-" + GetEnvironmentSettings() + "-trn";
string fileName = "";
string[] fileStr = S3Path.Split('-');
if (fileStr.Count() > 0)
{
fileName = fileStr.Last();
}
Stream responseStream = await _imageStore.GetImage(bucket, S3Path);
if (responseStream == null)
return NotFound();
using (MemoryStream ms = new MemoryStream())
{
responseStream.CopyTo(ms);
var finalResult = File(System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray()), MimeTypesMap.GetMimeType(S3Path), fileName);
return Ok(finalResult);
}
}
catch (Exception ex)
{
return StatusCode(500, "Error in downloading file.");
}
}
public async Task<Stream> GetImage(string bucketName, string objectKey)
{
GetObjectRequest originalRequest = new GetObjectRequest
{
BucketName = bucketName,
Key = objectKey
};
try
{
GetObjectResponse response = await S3Client.GetObjectAsync(originalRequest);
// AWS HashStream doesn't support seeking so we need to copy it back to a MemoryStream
MemoryStream outputStream = new MemoryStream();
response.ResponseStream.CopyTo(outputStream);
outputStream.Position = 0;
return outputStream;
}
catch (AmazonS3Exception ex)
{
// Not found if we get an exception
return null;
}
}
I have such function in the front-end as below,
function saveTextAsFile(data, filename, contentType) {
if (!data) {
console.error('Console.save: No data')
toastr.error("No data received from server");
return;
}
if (!filename) filename = 'noname.xlsx';
var blob = new Blob([s2ab(atob(data))], {
type: contentType
});
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
}
and function
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
This function is working fine with excel that only has normal text. However, this excel i am trying to download, it has rich content such as color border, dropdown, multiple sheets.
When I try to use this same function to download the excel file, it throw me this error:
To help you more understand my problem, here is t he API HTTP CAll
I have try to search solution online but there is no luck. I actually do not understand what is the problem here. Anything will help thanks.
Thanks for all the replies and make my head around a little bit finally I fixed this issue.
Well, found the problem with it is because in the API I wrap that inside UTF-8. however, it (Excel) shouldn't be wrapped in UTF-8. only If I was downloading a csv file.
var finalResult = File(System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray()),
MimeTypesMap.GetMimeType(S3Path), fileName);
Changed to
var finalResult = File(ms.ToArray(), MimeTypesMap.GetMimeType(S3Path), fileName);
I created a service to download a PDF file.
On my server-side(Java) the PDF is generated successfully. But I am unable to download that on the UI side (Using Jquery Ajax call).
Could anyone please help me with this?
$(document).on('click', '.orderView', function(event){
orderId = $(this).attr('data');
$.ajax({
type : 'GET',
contentType : 'application/json',
url : '../service/purchase/generateInventoryPurchasePdf/'+orderId,
success : function(response) {
console.log("Success");
},
error : function(response) {
console.log("Error :" + response);
}
});
});
Java Code:
#RequestMapping(value = "/generateInventoryPurchasePdf/{purchaseId}", method = RequestMethod.GET)
public ResponseEntity<ByteArrayResource> generateInventoryPurchasePdf(HttpServletResponse response,#PathVariable("purchaseId") Long purchaseId) throws Exception {
PurchaseOrder purchaseOrder = null;
purchaseOrder = purchaseService.findByPurchaseOrderId(purchaseId);
// generate the PDF
Map<Object,Object> pdfMap = new HashMap<>();
pdfMap.put("purchaseOrder", purchaseOrder);
pdfMap.put("purchaseOrderDetail", purchaseOrder.getPurchaseOrderDetail());
pdfMap.put("vendorName", purchaseOrder.getInvVendor().getName());
pdfMap.put("vendorAddrs", purchaseOrder.getInvVendor().getVenAddress().get(0));
File file = util.generatePdf("email/purchasepdf", pdfMap);
MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, file.getName());
System.out.println("fileName: " + file.getName());
System.out.println("mediaType: " + mediaType);
//Path path = Paths.get(file.getAbsolutePath() + "/" + file.getName());
Path path = Paths.get(file.getAbsolutePath());
byte[] data = Files.readAllBytes(path);
ByteArrayResource resource = new ByteArrayResource(data);
return ResponseEntity.ok()
// Content-Disposition
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + path.getFileName().toString())
// Content-Type
.contentType(mediaType) //
// Content-Lengh
.contentLength(data.length) //
.body(resource);
}
mediaUtil class:
public class MediaTypeUtils {
public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {
// application/pdf
// application/xml
// image/gif, ...
String mineType = servletContext.getMimeType(fileName);
try {
MediaType mediaType = MediaType.parseMediaType(mineType);
return mediaType;
} catch (Exception e) {
return MediaType.APPLICATION_OCTET_STREAM;
}
}
}
PDF Generation code:
public File generatePdf(String templateName, Map<Object, Object> map) throws Exception {
Assert.notNull(templateName, "The templateName can not be null");
Context ctx = new Context();
if (map != null) {
Iterator<Entry<Object, Object>> itMap = map.entrySet().iterator();
while (itMap.hasNext()) {
Map.Entry<Object, Object> pair = itMap.next();
ctx.setVariable(pair.getKey().toString(), pair.getValue());
}
}
String processedHtml = templateEngine.process(templateName, ctx);
FileOutputStream os = null;
String fileName = "POLIST";
try {
final File outputFile = File.createTempFile(fileName, ".pdf",new File(servletContext.getRealPath("/")));
outputFile.mkdir();
os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(processedHtml);
renderer.layout();
renderer.createPDF(os, false);
renderer.finishPDF();
System.out.println("PDF created successfully");
return outputFile;
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
}
}
I'm not getting any error, PDF generate successfully in the server side. But In UI side not working.
Downloading files via AJAX isn't really a logical thing to do. When you make an AJAX call, the data returned from the server is returned into your page's JavaScript code (in the response callback value), rather than being returned to the browser itself to decide what to do. Therefore the browser has no way to initiate a download, because the browser is not directly in control of the response - your JavaScript code is in control instead.
As you've indicated in your comment below the question, there are workarounds you can use, but really the best approach is simply to use a regular non-AJAX request to download
For instance you could replace your jQuery code with something like
$(document).on('click', '.orderView', function(event){
orderId = $(this).attr('data');
window.open('../service/purchase/generateInventoryPurchasePdf/'+orderId);
});
This will download the document from a new tab without navigating away from the current page.
I try to export excel from a function in my data access layer which return dataTable. Now my question is why my Response.end return an error.
The datagrid have datas
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.
My export code
if (command == "export") {
StringWriter osStringWritter = new StringWriter();
Html32TextWriter osHtmlTextWritter = new Html32TextWriter(osStringWritter);
DataTable dt = new DataTable();
DataGrid dgv = new DataGrid();
PostTransDA transaction = new PostTransDA();
try {
dt = transaction.getTransaction(from_Dates, to_dates);
if (dt.Rows.Count > 0) {
Response.Clear();
Response.Buffer = false;
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("content-disposition", string.Format("attachment;filename={0}.xls", "TransactionReport"));
Response.Charset = "";
dgv.DataSource = dt;
dgv.DataBind();
dgv.RenderControl(osHtmlTextWritter);
Response.Write("Report Date:" + DateTime.Now);
Response.Write(osStringWritter.ToString());
Response.End();
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
dgv = null;
osStringWritter = null;
osHtmlTextWritter = null;
}
}
catch (Exception ex)
{
ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "Script", "alert('" + ex.Message + "');", true);
}
}
its return the error on the part of Response.End()
what im doing wrong? or what is the problem in my code
Please check link given below for issues you have. You need to handle ThreadAbortException when you are using either Response.End or Response.Redirect or Server.Transfer.
Microsoft link for Best practices to avoid ThreadAbortException
I'm using the code below for downloading with the web API in ASP.NET.
When I'm trying to click the download button, it calls the API.
After executing the "DownloadFile"-function, the download dialog box isn't coming .
[HttpGet]
public HttpResponseMessage DownloadFile(string DownloadFilePath)
{
HttpResponseMessage result = null;
var localFilePath = HttpContext.Current.Server.MapPath(DownloadFilePath);
// check if parameter is valid
if (String.IsNullOrEmpty(DownloadFilePath))
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
// check if file exists on the server
else if (!File.Exists(localFilePath))
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{// serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = DownloadFilePath;
}
return result;
}
I didn't get any exception from the code above, but the dialog box for downloading the file isn't coming.
Here is the code, I am using and it works great. I hope it will give you an idea
....
var fileBytes = Helper.GetFileBytes(filePath);//convert file to bytes
var stream = new MemoryStream(fileBytes);
resp.Content = new StreamContent(stream);
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
resp.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = filerequest.FileName };
resp.Content.Headers.Add("Content-Encoding", "UTF-8");
return resp;
And, here is the code for GetFileBytes method,
public static byte[] GetFileBytes(string filePath)
{
var fileInfo = new FileInfo(filePath);
if (fileInfo.Exists)
{
return File.ReadAllBytes(fileInfo.FullName);
}
return null;
}
Any help is most welcomed and really appreciated.
I have an MVC action which retries a file content from a web service. This action is invoked from a Angular service (located in services.js) using $http.post(action, model), and the action is returning a FileContentResult object, which contains the byte array and the content type.
public ActionResult DownloadResults(DownloadResultsModel downloadResultsModel)
{
downloadResult = ... // Retrieving the file from a web service
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", downloadResult.FileName));
Response.BufferOutput = false;
return new FileContentResult(downloadResult.Contents, downloadResult.ContentType);
}
The issue I'm having is about the browser not performing the default behavior of handing a file (for example, prompting to open it, saving it or cancel). The action is completed successfully with having the content of the file and the file name (injected to the FileContentResult object), but there s no response from the browser.
When I'm replacing the post with $window.location.href, and construct the URI myself, I'm hitting the action and after it completes the browser is handling the file as expected.
Does anyone can think of any idea how to complete the 'post' as expected?
Thanks,
Elad
I am using below code to download the file, given that the file does exist on the server and client is sending server the full path of the file...
as per you requirement change the code to specify path on server itself.
[HttpGet]
public HttpResponseMessage DownloadFile(string filename)
{
filename = filename.Replace("\\\\", "\\").Replace("'", "").Replace("\"", "");
if (!char.IsLetter(filename[0]))
{
filename = filename.Substring(2);
}
var fileinfo = new FileInfo(filename);
if (!fileinfo.Exists)
{
throw new FileNotFoundException(fileinfo.Name);
}
try
{
var excelData = File.ReadAllBytes(filename);
var result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream(excelData);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileinfo.Name
};
return result;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.ExpectationFailed, ex);
}
}
and then on client side in angular:
var downloadFile = function (filename) {
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.src = document.location.pathname + "api/GridApi/DownloadFile?filename='" + escape(filename) + "'";
ifr.onload = function () {
document.body.removeChild(ifr);
ifr = null;
};
};