Pdf document as response for ajax call - c#

I need a script that passes a json string to a function in the controller and process the response pdf document to be seen as downloads to the user.
I return a pdf document of FileResult data type in c# as the response for an ajax call which passes a JSON string to the function.
I need this pdf document to be seen as downloads to the user. How can I perform this? I tried to write code in the success of ajax but the control goes to error and by debugging I found it to be a parse error.
Ajax code is like
function Download(){
$.ajax({
method: "POST",
url: "{url to the action}",
data: {
//Send json data that you want
}
success:function (e){
alert('success');
},
error:function(){
alert("error");
}
})
}
C# code is like:
public FileResult getPDF(string statementHTML)
{
//code to convert to pdf file
File file = //pdf document with MIME 'apllication/pdf'
return file;
}
When the above code executes the error alert is invoked but this c# function returns a pdf document but seems like ajax don't accept it.

You don't really need to ajax to make this download call, you can just do this.
function DownloadFile(){
//do some calculation
window.location="{url to the action}?argument1=value1&argument2=value2....."
}
However if you have to do it via ajax, you can get download.js and do this.
function DownloadFileUsingAjax(){
$.ajax({
url: "{url to the action}",
data: {
//Send json data that you want
}
})
.done(function(data){
//download function is from download.js
download(data, fileName, fileMimeType);
});
}

For another way, you could try mock the button click event to download the file like
Client Side.
#section Scripts{
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
url: '/Home/GetPDF',
method: 'get',
contentType:'application/json',
xhrFields: {
responseType: 'blob'
},
success: function (data, status, response) {
var filename = "";
var disposition = response.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
let a = document.createElement('a');
a.href = window.URL.createObjectURL(data);
a.download = filename;
document.body.append(a);
a.click();
window.URL.revokeObjectURL(url);
}
});
});
</script>
}
Controller
public FileResult GetPDF(string statementHTML)
{
var fileByte = System.IO.File.ReadAllBytes(#"xxx\Test.pdf");
return File(fileByte, "apllication/pdf", "Test.pdf");
}

Related

Download file with ajax in C# .net MVC

I have tried to use the following code to download file with ajax in C# .net MVC. For some reason, there is not working. Does anyone know why?
I'm expecting the file will be download or a window dialog will be pop up to ask for the user to select the save directory once function downloadFile have been call
Javascript:
function downloadFile(even) {
$.ajax({
url: "/Home/Download",
type: "POST",
data: {
fileName: even.id
},
success: function (returnValue) {
window.location = returnValue;
},
error: function (data) {
}
});
}
C# script:
[Authorize]
[HttpPost]
public virtual FileResult Download(string fileName)
{
var file = (fileName.Contains("hl7s") == true ? fileName + ".zip" : fileName + ".txt");
byte[] fileBytes = System.IO.File.ReadAllBytes(#"c:\temp\"+ file);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
It is not that straight forward to do this, however, there is a script that can help you. I normally use FileSaver.js to do this, it is open source. FileSaver helps solve browser incompatibilities, it is well tested too.
Here is a code snippet I lift from my current project. This is plain javascript and does not require jQuery or anything.
In this sample, the filename is hardcoded to 'my_excel_file.xlsx', but you can get the filename from the api if you expose a proper header from the api. I think I answered how to handle that somewhere in SO.
<html>
<head>
<script src="FileSaver.min.js"></script>
<script>
function download() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://your.url", true);
xhr.setRequestHeader("Content-type","application/json");
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.setRequestHeader("Accept", "application/octet-stream");
//xhr.setRequestHeader("Authorization", "Bearer ......");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var blob = new Blob([xhr.response], {type: "octet/stream"});
var fileName = "my_excel_file.xlsx";
saveAs(blob, fileName);
}
}
xhr.responseType = "arraybuffer";
xhr.send();
}
</script>
</head>
<body>
<button onclick="javascript:download()">Download Excel File</button>
</body>
</html>
Just use HTML download attribute to download file
<a href="you file location" download></a>
Please refer this link for more information

How to check a received file bytes by web API and save on the sever?

I have to write a service using Web API. In that method I should receive 2 items:
An Id,
File(s)
This method is going to be called from a mobile app. After googling on the subject, in a sample web page, I converted uploaded file to base 64 (using jQuery) and I received it on the server:
<script type="text/javascript">
// Holds the load event results
var base64 = "";
//
function converToBase64() {
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
// Event handler
reader.addEventListener("load", function () {
base64 = reader.result;
console.log(base64);
}, false);
// Fires the load event
if (file) {
reader.readAsDataURL(file);
}
}
// AJAX request
$(function () {
$('#Button1').click(function () {
var data = {};
data.Id = "3";
data.File = base64;
console.log(data);
alert("start");
$.ajax({
type: "POST",
url: "/api/SaveFile",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
dataType: "json"
}).done(function (result) {
console.log(result);
});
})
});
</script>
<div>
<input type="file" onchange="converToBase64()"><br>
<input id="Button1" type="button" value="Submit" />
</div>
I have no idea whether my solution is correct. Anyway, after receiving on server side, I converted base 64 string to byte[].
[HttpPost]
public HttpResponseMessage Post(FileUploadData data)
{
string converted = data.File.Substring(data.File.IndexOf(",") + 1, data.File.Length - data.File.IndexOf(",") - 1);
byte[] fileBytes = Convert.FromBase64String(converted);
// Do checking
return Request.CreateResponse(HttpStatusCode.OK, "Success");
}
public class FileUploadData
{
public string Id { get; set; }
public string File { get; set; }
}
I've read lots of solutions to same problem about saving bytes into files. But I should not do this before checking extension and size. As it is dangerous to save banned files on physical space, So how can I do these checking before saving on the disk(as a file)? Because .

Request URL Too Long

I getting this error "Request URL Too Long" when i tried to download the file. The url shows the data that i want to download but it doesn't download.
How can i solve Request URL Too Long error when downloading
my code
Javascript
<script>
function DownloadIndexController(possID) {
$.ajax({
url: '#Url.Action("DownloadIndex", "Poss")',
contentType: 'application/json; charset=utf-8',
datatype: 'json',
data: { possID: possID },
type: "GET",
success: function (returnValue) {
window.location = '/DownloadIndex/Poss' + returnValue;
}
})
}
</script>
Controller
[HttpGet]
public virtual ActionResult DownloadIndex(int possID)
{
try
{
possFilename = possFilename.Replace(",", ",");
string fullPath = Filelocation + possFilename;
return File(fullPath, System.Net.Mime.MediaTypeNames.Application.Octet, possFilename);
}
catch (Exception ex)
{
throw ex;
}
You cannot use ajax to download a file in that way.
What you need to do is to generate a normal download link for every item in your grid, like:
#Html.ActionLink("Download", "DownloadIndex", "Home", new { possID = "123" }, null)
Where Home is the name of your controller, and you have to dynamically add the possID for every item instead of the hard coded 123 in my example.
In your code, you download the file using ajax, and then you redirect to an url containing the full file just after '/DownloadIndex/Poss'
You probably just want to redirect to the file, without using Ajax at all :
<script>
function DownloadIndexController(possID) {
window.location = '/DownloadIndex/Poss?possID=' + possID;
}
</script>

Download file using ajax

I have a submit button on a form, when it's pressed the form is submitted and an Excel file is created on the server harddrive (C:/ExcelFiles).
After this has been done (after de form is submitted) I want to download this file using Ajax.
This is what I've done but it's not working:
$(document).on('click', '#saveButton', function () {
$('#saveMessage').empty();
$('#saveMessage').append("<p>Your file has been stored in C:\\ExcelFiles</p>");
var data = $('#fileName').val();
alert(data);
$.ajax({
type: 'POST',
url: '/Calculation/Download',
data: data,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (returnValue) {
window.location = '/Calculation/Download?fileName=' + returnValue;
}
});
});
And my controller action look like this:
[HttpGet]
public virtual ActionResult Download(string fileName)
{
string fullPath = Path.Combine(Server.MapPath("~/ExcelFiles"), fileName);
return File(fullPath, "application/vnd.ms-excel", fileName);
}
Right now nothing happens. What am I doing wrong?
You cannot download files from the server by .ajax (due to security reasons).
You can however point the browser to that location and download the file.
The solution should be something like this:
$(document).on('click', '#saveButton', function () {
$('#saveMessage').empty();
$('#saveMessage').append("<p>Your file has been stored in C:\\ExcelFiles</p>");
var data = $('#fileName').val();
window.location = '/Calculation/Download?fileName=' + data ;
});

Pass UploadFile content as byte[] or object from jquery ajax function and upload via webmethod

I have an html page which contains a form with file upload input.
I need to pass all the fields in jquery ajax function to an aspx page containing a WebMethod and in this method I should upload the image to the website file system and not as bytes in the database.
Is this doable using jquery ajax with webmethod in c#
If you want to save the file to the Website file system than yes this is doable. I ran into a same scenario of uploading the files usinga webmethod and saw this question. I solved the problem so though of sharing my solution. Hope it will help someone.
Below is the code in which we create a FormData object and append our files to it and then pass this FormData object to the WebMethod through Jquery Ajax.
var Upload = function () {
var fileInputCtrl = $('<input id="File_OpenInputCtrl" type="file" style="position: fixed; top: -100em" multiple/>');
fileInputCtrl.off('change').on('change', function (evt) {
var files = evt.target.files;
var fd = new FormData();
for (var f = 0; f < files.length; f++) {
var file = files[f];
fd.append(file.name, file);
}
// Upload the formdata
$.ajax({
url: "Webservice.asmx/UploadFiles",
type: "POST",
data: fd,
contentType: false,
processData: false,
success: function (result) {
alert(result);
$('#File_OpenInputCtrl').remove();
},
error: function (err) {
alert(err.statusText);
$('#File_OpenInputCtrl').remove();
}
});
});
fileInputCtrl.click();
}
The WebMethod
public string UploadFiles()
{
//this function handles the upload of gallery images and magazine file
var Request = HttpContext.Current.Request;
System.Web.HttpFileCollection Files = Request.Files;
try
{
for (int i = 0; i < Files.Count; i++)
{
System.Web.HttpPostedFile File = Files[i];
File.SaveAs(HttpContext.Current.Server.MapPath("~/Uploads/" + File.FileName));
}
return "Files Saved Successfully!";
}
catch (Exception ex)
{
return ex.Message;
}
}
Hope it Helps.

Categories

Resources