I have Export to Excel button in my HTML page, onClick of the button i will send GET request to ASP .Net Web API, which which get data from Database and return HTTPContext binary Response. In the front end, i am getting binary data of the Excel file. How to directly download the file once response came?
HttpContext.Current.Response.ClearContent();
FileStream objFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
byte[] excelResponse = new byte[objFileStream.Length];
objFileStream.Read(excelResponse, 0, excelResponse.Length);
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", fileName));
HttpContext.Current.Response.BinaryWrite(excelResponse);
My front end binary content
PKS��J�ɉ�fxl/workbook.xml �(��P�N�0����SA5������8�����4�Z^���8�I�n"�+�Y�����|}����ጉ�V,����V�����v��OJ�=�
How to download as file? I dont want to use form
Below is the AJAX call i am making on click on Export button.
// Make AJAX call
$.ajax({
type: "GET",
url: "http://localhost:8899/api/ExportDataToExcel/",
data: oData,
headers: {
"Authorization": "Bearer " + sToken,
},
success: function (oResult) {
onSuccess(oResult);
},
error: function (oResponse) {
onFailure(oResponse);
}
});
That's all i am doing on Export to Excel button click.
If i use Form submit, then i am getting Authorization denied error, as the API expects bearer token. Following code gives Authorization denied error
var form = document.createElement("form")
form.action = url + 'exportDataToExcel/';
form.method = "GET";
document.body.appendChild(form);
form.submit(true);
document.body.removeChild(form);
I resolved the issue by replacing AJAX with XMLHttpRequest, as AJAX can't receive binary buffer response. Once i received response for XHR, i am creating JavaScript Blob and then anchor tag and redirecting that anchor element to BlobObjectURL.
Related
I am using JQuery to send an AJAX request to a Node server (using Hapi). The server responds with a PDF file correctly, but I am trying to save the file locally. The catch is that the PDF should only return if the POST sent the right data. It's "protected" in other words and I don't want to just expose it publicly.
Frontend code:
$.get('http://localhost:3000').done(function (data) {
console.log(data);
});
Backend code:
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
return h.file('./static/sample.pdf', {
mode: 'attachment',
filename: 'sample.pdf'
})
}
});
I receive the data but nothing happens in the front-end UI. How can I download the PDF that is sent automatically?
You can achieve that with html5 using
Download it!
Notice that this works only for same-origin URLs, or the blob: and data: schemes. And this gets overridden by the Content-Disposition header from the server.
If you want to do this programatically you could do this
const element = document.createElement("a")
element.setAttribute(
"href",
// you could also use base64 encoding here like data:application/pdf;base64,
"data:text/plain;charset=utf-8," + encodeURIComponent('pdf binary content here')
)
element.setAttribute("download", "file.pdf")
element.style.display = "none"
document.body.appendChild(element)
element.click()
document.body.removeChild(element)
Anyway this is only a useful method if u want to create/modify the downloaded data from the client side, but if u are getting it as it is from the server side then its better just to open a new url, letting the browser handle it.
Can you please let me know how I can get a ZIP file stored on same server using the jquery Ajax? Please be informed that I do not want to download the file
I need to pass the result , if success? to an API snippet like this, (this is using a Form to pass a zip file from client to the request Here is The Working Demo
request({
url: portalUrl + '/sharing/rest/content/features/generate',
content: myContent,
form: dom.byId('uploadForm'),
handleAs: 'json',
load: lang.hitch(this, function (response) {
if (response.error) {
errorHandler(response.error);
return;
}
var layerName = response.featureCollection.layers[0].layerDefinition.name;
addShapefileToMap(response.featureCollection);
}),
error: lang.hitch(this, errorHandler)
});
but I need to pass the zip file from server witout using a form and here is what I would like to do
var data = "www.mydomain.com/GIS/App.ZIP";
request({
....,
form: data,
....
});
Update
As menitoned API offers the Formdata option as well but how I can pass second parameter of type inside the append method?
var theFile = "http://localhost/Portal/APP.ZIP";
var myFormData = new FormData();
myFormData.append(theFile, ? );
Javascript cannot access the local filesystem without user intervention for security reasons. A user must take an action to load a file. Otherwise, it would be very easy for malicious web pages to traverse your file system.
You can use javascript via AJAX to trigger a server side script which can access the server file system and return results to javascript though.
I am using JSPDF to dynamically generate a PDF with user information on my web app, which is built in React.js and hosted on Firebase.
On the final page, I would like to email this PDF to a list of addresses that the user specifies. This sounds straightforward, but I have encountered some issues. Firstly, I cannot send an email using just React.js. Doing some research has led me to create a request to a PHP file that uploads the file. In the PHP file, I then use the standard PHP mailer to send the emails.
JSPDF has these functions used to export the file:
var pdfInBase64 = doc.output('datauristring');
var pdfInRawFormat = doc.output();
Here are 2 of my attempts to solve this issue. Both use FormData.
var formData = new FormData();
formData.append("data", pdfInBase64); // also tried pdfInRawFormat
Using XMLHttpRequest:
var xhr = new XMLHttpRequest();
xhr.open('POST', 'uploader.php', true);
xhr.onload = function () {
if (xhr.status === 200) {
// File(s) uploaded.
console.log('completed');
} else {
alert('An error occurred!');
}
};
xhr.send(formData);
Using AJAX:
var $ = require ('jquery');
$.ajax({
type: "POST",
url: 'uploader.php',
data: formData,
dataType: 'json',
contentType: false,
processData: false
});
Both of the above methods don't seem to be working for me. When I go to my console and look at the "Networking" tab, I see that a request has been made, but it times out after 20+ seconds. I tried not uploading a file and just setting data as hello or any other string, and the PHP file successfully receives it. I'm thinking that the file that I have is too large, leading to a timeout.
Could someone please point me in the right direction on how to fix this? My end goal is to send an email with an attachment using JavaScript and PHP. Thanks!!
I'm trying to generate a PDF file with HTML content that's being sent via AJAX from JavaScript.
I have the HTML being sent properly, and the PDF being generated correctly using the HTML, but I'm stuck trying to figure out how to initiate the file download on the user's browser.
This is what I'm currently trying. This works in a IHttpHandler file when hitting the URL for the file directly, but doesn't work in the ApiController when posting via AJAX.
I've also tried posting to the IHttpHandler file with the same results. Everything works fine until I try to initiate the download by using BinaryWrite.
public class DownloadScheduleController : ApiController
{
public void Post(HtmlModel data)
{
var htmlContent = data.html;
var pdfBytes = (new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(htmlContent);
using (var mstream = new System.IO.MemoryStream())
{
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AppendHeader("content-disposition", "attachment; filename=UserSchedule.pdf");
HttpContext.Current.Response.BinaryWrite(pdfBytes);
HttpContext.Current.Response.End();
}
}
}
Here is the Ajax request. It's using Angular's $http.
$http({
method: 'POST',
url: 'api/downloadSchedule',
dataType: "json",
contentType: "application/json; charset=utf-8",
data: data
});
Alternatively I could return the PDF binary to JavaScript, but then how do I use JavaScript to save the pdf?
Any help will be greatly appreciated.
For security reasons, the browser cannot initiate a file download from an AJAX request. It can only be done by navigating to a page that sends a file.
Usually if you need to initiate a download from Javascript, you would either set window.location.href = urlToFile, or create a new iframe pointing to that url.
In your case this would not serve, because the above methods only perform a GET request, and you need a POST, so I only see two possible solutions to this:
you could modify your JS to - instead of submitting the request with $http - create an HTML form with fields that correspond to what you originally posted with your AJAX request, then append the form to the page, populate the fields and submit the form
or you could change your server-side code as well as your Javascript.
If you opt for the second solution, you could follow the approach of using two methods on the server side:
one POST that generates the file and saves it in the cache (there are probably better solutions that using the cache, especially if you're on a server farm, but let's keep it simple)
one GET that that retrieves the cached content and returns it to the user. In this way you will be able to post the data via an AJAX call, and then getting the file by navigating to the right url.
Your C# code would look something like this:
public class DownloadScheduleController : ApiController
{
public object Post(HtmlModel data)
{
var htmlContent = data.html;
var pdfBytes = (new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(htmlContent);
var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30), Priority = CacheItemPriority.NotRemovable };
var cacheId = Guid.NewGuid().ToString();
MemoryCache.Default.Add("pdfBytes_" + cacheId, pdfBytes, policy);
return new { id = cacheId };
}
public void Get(string id)
{
var pdfBytes = MemoryCache.Default.Get("pdfBytes_" + id);
MemoryCache.Default.Remove("pdfBytes_" + id);
using (var mstream = new System.IO.MemoryStream())
{
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AppendHeader("content-disposition", "attachment; filename=UserSchedule.pdf");
HttpContext.Current.Response.BinaryWrite(pdfBytes);
HttpContext.Current.Response.End();
}
}
}
Your frontend could then be something like:
$http({
method: 'POST',
url: 'api/downloadSchedule',
dataType: "json",
contentType: "application/json; charset=utf-8",
data: data
}).success(function(response) {
// note: the url path might be different depending on your route configuration
window.location.href = 'api/downloadSchedule/' + response.id;
});
Keep in mind that my code is just meant to show you the approach, it's not meant to be used as it is in production. For example, you should definitely clear the cache immediately after use. You should also make sanity checks in your Get method for what is retrieved from the cache, before using it. Also, you might want to take additional security precautions on the data that you store and retrieve, depending on your requirements.
I have an ajax call that successfully calls a page that by itself works fine. You click the button, and a PDF downloads. However, when I make an AJAX call using the same request type and url, the data is returned, but does not prompt a download.
My call :
$("#download-pdf").live('click', function(){
$.ajax({
url: $(this).parents('form').attr('action'),
type: 'POST',
success: function(data){
console.log(data);
}
});
return false;
});
Data is returned as what would be an unparsed PDF. So I know the information is there. It just doesn't cause a download. Any tricks?
The only way to force a download is to refresh the page using the "standard" form submission method. With Ajax you'll receive the raw output data (PDF) and no save dialog will ever pop up
It's not possible to force downloading when using AJAX.
Please read this: Force download a pdf link using javascript/ajax/jquery
If you would just submit the form then you can tell the browser to download the file by sending the appropriate headers:
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=file.pdf");
Response.ContentType = "application/pdf";
Response.WriteFile(Server.MapPath(#"~/file.pdf"));
Response.End();