how to allow file download in asp.net from dynamically generated table - c#

I am using elasticsearch to query in index of PDFs on a asp.net mvc app. When I get the result I would like the user to be able to click the returned filename to download that file. Researching how to enable this functionality has returned plenty of results but none seem to work for me. I would simply like the user to be able to click on the filename and have the file download for them. I am using the below code.
To generate the dynamic table with search results
var row = $("<tr><th>" + "Search Results" + "</th><th>" + "File Name" + "</th>");
$("#myTable").append(row);
for (var i = 0; i < response.datasend.length; i++) {
var pos = response.datasend[i].Attachment.Content.indexOf(obj.searchterm);
var row = $("<tr><td>" + response.datasend[i].Attachment.Content.slice((pos - 100), (pos + 100)) + "</td><td><a href=# id=fileName>"
+ response.datasend[i].filename + "</a></td></tr>");
$("#myTable").append(row);
}
To detect the requested filename and call the function to start the download process
var table = document.getElementById("myTable");
table.addEventListener("click", function(e) {
if (e.target && e.target.id == "fileName")
{
var apiUrl = "/AllSearch/Download";
var obj = {};
obj.searchterm = e.target.innerHTML;
var params = e.target.innerHTML;
$.ajax({
contentType: 'application/json',
url: apiUrl,
dataType: "json",
data: {fileName: obj.searchterm},
success: function(data) {
alert("success");
},
error: function (xhr, err) {
alert("ready state: " + xhr.readyStat + " " + xhr.status);
}
});
}
});
To start download the file
public ActionResult Download(string fileName)
{
string filename = fileName;
string filePath = #"C:;at\to\file\Documents\" + fileName;
byte[] filedata = System.IO.File.ReadAllBytes(filePath);
string contentType = MimeMapping.GetMimeMapping(filePath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = true,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
The Download function is from Returning a file to View/Download in ASP.NET MVC but it returns an error when I run it. Not sure what I am missing here. Any help is appreciated

Related

FileDownload Not working ASP MVC

I'm trying to download a file from server but this thing won't work. Been tring doing it for more than 2 weeks. Here is the code:
IN CSHTML PAGE:
<script type="text/x-jsrender" id="docView">
View
</script>
<script>
function docView(id) {
docId = id;
$.ajax({
type: "GET",
url: '#Url.Action("DownloadFile", "Profile")' + "?docid=" + docId,
dataType: "json",
success: function (result) {
},
});
</script>
IN MVC Controller:
[HttpGet]
public ActionResult DownloadFile(Guid? docid)
{
int i = 1;
string key = ConfigurationManager.AppSettings["PhysicalDocumentPath"];
JApplicantDocument value = new JApplicantDocument();
var response = new Response();
var fName = "";
var savefileName = "";
var fileSavePath = "";
var prevPath = "";
var nextPath = "";
try
{
IApplicantDataService applicantDataService = new ApplicantDataService();
response = applicantDataService.GetDocument(docid, value);
var fileName = value.ApplicantId + "_" + value.DocumentName;
fName = fileName;
savefileName = fileName;
fileSavePath = Path.Combine(key, fileName);
prevPath = fileSavePath;
nextPath = fileSavePath;
var tmp = fileName.Split('.');
var tmp1 = tmp[0];
while (System.IO.File.Exists(nextPath)) //to get the latest file
{
tmp = fileName.Split('.');
fileName = tmp1 + i.ToString();
fileName = fileName + "." + tmp[1];
savefileName = fileName;
nextPath = Path.Combine(key, savefileName);
if (System.IO.File.Exists(nextPath))
{
prevPath = nextPath;
}
i++;
tmp = prevPath.Split(new string[] { "Docs\\" }, StringSplitOptions.None);
fName = tmp[1];
response.Message = prevPath;
}
}
catch (Exception e)
{
Utils.Write(e);
}
return File(prevPath, value.Format);
}
I just want on click of View button to download the file as per this(http://www.c-sharpcorner.com/UploadFile/db2972/file-download-sample-in-mvc-day-40/). i cannot use location.href(...) directly in tag due to the fact that i'm using it in script jsrender which is being used in syncfusion grid controls. Hence I wont be able to get the docid at all.

Why downloading a file throws multiple disposition error ?

I am using a webgrid and I have put a download button inside it to download a file from the grid.
But it throws an error: localhost sent an invalid response.
ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
[HttpGet]
public ActionResult DownloadStories()
{
string filename = "saddam.png";
string filepath = Server.MapPath("~/UploadedFiles/") + filename; //AppDomain.CurrentDomain.BaseDirectory + "/UploadedFiles/" + filename;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = MimeMapping.GetMimeMapping(filepath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = true,
};
// Response.AppendHeader("Content-Disposition", cd.ToString());
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
return File(filedata, contentType, cd.FileName);
}
View:
WebGrid wgImages = new WebGrid(listData, rowsPerPage: 20);
#wgImages.GetHtml(tableStyle: "table table-condensed table-bordered table-striped table-responsive",
columns: wgImages.Columns(
wgImages.Column
(columnName: "Image", header:"Image"),
wgImages.Column
(columnName:"Story", header: "Story"),
wgImages.Column
(columnName:"Image", header:"Download", format: (testItem)=> Html.ActionLink("Download", "DownloadStories", "Stories")
))
);
}
I have tried the code which I have commented now and that doesn't work too.
Why not use simple HTML & JAVASCRIPT TO download the file by making an ajax call
1. Call this funcation by ajax post
[HttpPost]
public JsonResult DownloadStories(String someParamsIfany)
{
//do your thing
return Json(file,JsonRequestBehavior.AllowGet);
}
2. create an Img file with the data & download it on Html Side
$.ajax({
type: "POST",
url: '/Home/DownloadStories',
data: {someParamsIfany :someParamsIfany},
success: function (result) {
DownLoadTheFile(result);
}
});
3 now function DownLoadTheFile
function DownLoadTheFile(file){
var a = document.createElement('a');
a.href = file.filepath ;
a.download = file.filename;
a.click();
}

Refresh in browser when uploading mvc file c #

I have an AJAX file upload by call to MVC C# driver, but the browser refreshes and reloads the page.
But if I comment the line that saves the file in the driver does not happen that is only when the file is saved on the server. File.SaveAs (fname);
MVC controller:
[HttpPost]
public ActionResult UploadDocument()
{
if (Request.Files.Count > 0)
{
try
{
FileUpdateDto fileModal = new FileUpdateDto();
HttpFileCollectionBase files = Request.Files;
for (int i = 0; i < files.Count; i++)
{
HttpPostedFileBase file = files[i];
string fname;
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Content/Document/" + UserId).ToString());
if (!directory.Exists)
{
Directory.CreateDirectory(Server.MapPath("~/Content/Document/" + UserId).ToString());
}
if (Request.Browser.Browser.ToUpper() == "IE" || Request.Browser.Browser.ToUpper() == "INTERNETEXPLORER")
{
string[] testfiles = file.FileName.Split(new char[] { '\\' });
fname = testfiles[testfiles.Length - 1];
}
else
{
fname = file.FileName;
}
var guidnew = Guid.NewGuid();
fname = Path.Combine(Server.MapPath("~/Content/Document/" + UserId), guidnew + "." + fname.Split('.')[1].ToString());
fileModal.FileName = fname;
fileModal.Path = directory.ToString();
fileModal.DateFileUpload = DateTime.Now;
file.SaveAs(fname); // If I comment this line without refreshing the browser but does not save the file
}
return Json(fileModal);
}
catch (Exception ex)
{
return Json("Error occurred. Error details: " + ex.Message);
}
}
else
{
return Json("No files selected.");
}
}
Call Ajax in JavaScript:
UploadDocument: function () {
if (window.FormData !== undefined) {
var fileUpload = $("#AdviserFileUpload").get(0);
var files = fileUpload.files;
var fileData = new FormData();
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
//fileData.append('username', 'Manas');
$.ajax({
url: site.baseUrl + '/Api/Upload/Document',
type: "POST",
contentType: false,
processData: false,
data: fileData,
success: function (result) {
__this._AdviserDocumentFile = result;
},
error: function (err) {
alert(err.statusText);
}
});
} else {
alert("FormData is not supported.");
}
}
I believe I found the solution. The cause is that Visual Studio's "Enable Reload on Save" property is True.
Go to Tools - Options - Web - Browser Reload on Save - Enable Reload on Save and make it false.
Im working with VS2015 and this worked for me, hope it works for you too.
Source

Returning a file path from webservice and opening it in a new window

I'm just trying to return the file path to the newly created PDF and open it in a new window.
When I run this code, I open a window that is 404 and goes to /null page. I'm assuming this means that I am being returned a null value from the CreateLabelPdf C# code.
Does anyone know why I am being returned null and how to fix it?
Javascript
function createLabelPdf(sampleIds, line1, line2, line3, loginMatrix, labelStart) {
var labelInfo = new Object();
labelInfo.sampleIds = sampleIds;
labelInfo.line1 = line1;
labelInfo.line2 = line2;
labelInfo.line3 = line3;
labelInfo.labelType = loginMatrix;
labelInfo.startingLabelPosition = labelStart;
$.ajax({
type: "POST",
url: "DesktopModules/DataManagement/TestService.svc/CreateLabelPdf",
data: JSON.stringify(labelInfo),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
window.open(data.d);
}
});
}
C# Service
[OperationContract]
public string CreateLabelPdf(List<string> sampleIds, string line1, string line2, string line3, string labelType, int startingLabelPosition)
{
List<LabelContent> labels = new List<LabelContent>();
foreach (var sample in sampleIds)
{
LabelContent labelContent = new LabelContent();
labelContent.Line1 = line1;
labelContent.Line2 = line2;
labelContent.Line3 = line3;
labelContent.LabelId = sample;
labels.Add(labelContent);
}
Creator creator = new Creator
{
IncludeLabelBorders = false
};
string path = HttpContext.Current.Server.MapPath(#"~\DesktopModules\DataManagement\Pdf\" + 0 + ".pdf");
creator.PrintLabels(labels, new Avery5160(), path, startingLabelPosition);
return path;
}
So I finally figured it out. I debugged the code and found out that the error was in this line:
string path = HttpContext.Current.Server.MapPath(#"~\DesktopModules\DataManagement\Pdf\" + 0 + ".pdf");
It was getting a null reference error so I changed the code to:
string path = System.Web.Hosting.HostingEnvironment.MapPath(#"~\DesktopModules\DataManagement\Pdf\" + 0 + ".pdf");
That worked but then I needed to return the relative string to the browser instead of the physcial path so I threw in:
string relativePath = #"\DesktopModules\DataManagement\Pdf\0.pdf";
return relativePath;
Ending code looking like:
string path = System.Web.Hosting.HostingEnvironment.MapPath(#"~\DesktopModules\DataManagement\Pdf\" + 0 + ".pdf");
creator.PrintLabels(labels, new Avery5160(), path, startingLabelPosition);
string relativePath = #"\DesktopModules\DataManagement\Pdf\0.pdf";
return relativePath;

jQuery calls asmx web method multiple times

I have a jQuery method that calls a .asmx web service. The jQuery method only executes one time but the web service executes multiple times.
this is the jQuery code that call the web service
// Expand copy to group modal groups
$(".groupZones .expand").live('click', function() {
$(this).siblings('.contract').show();
$(this).css('display', 'none');
$(this).parent().parent().siblings('.groupDetails').css('display', 'block');
$(this).parent().parent().siblings('.groupDetails').find('ul.device').find('ul .list').after('');
var cwpUserId = $('#ctl00_cphBody_hfCwpId').val();
var groupId = $(this).parent().siblings('.add').find('input').val();
sortOn = "Location";
var mode = "dayparts";
var groupUl = $(this).parent().parent().siblings('.groupDetails').find('ul').find('ul li.head');
var groupDetails = $(this).parent().parent().siblings('.groupDetails');
//Get the zone details..
// Load.
$.ajax({
type: "POST",
url: "ajax/DaypartMessagingGroups.asmx/GetDetailsForCopyToGroup",
data: "{'groupId':" + groupId + ",'cwpUserId':" + cwpUserId + ",'pageNum':0,'pageSize':5, 'sortOn':'" + sortOn + "','sortDirection':'" + sortDirection + "','mode':'" + mode + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
//$(btn).parents("ul.list-group-zones").children("li:.head").after(msg.d);
$(groupUl).after(msg.d);
$('.location').find('.contract').hide();
var copyZonePerPage = 5;
//var copyZoneItemsCount = $(groupUl).siblings('#hfAllGroupZones').val();
var copyZoneItemsCount = $('#hfAllGroupZones').val();
var copyZonePages = Math.ceil(copyZoneItemsCount / copyZonePerPage);
var copyZoneHtml = '';
var copyZoneCurLink = 0;
var current_copyzone_pagination_set = 1;
var num_of_pagination_shown = 0;
alert('Line 2113 CBG');
if (copyZonePages > 20) {
//var pagesAdded = (parseInt(current_copyzone_pagination_set) - 1) * 10;
while (num_of_pagination_shown < 20) {
copyZoneHtml += '<a class="page_link_clicked" longdesc="' + copyZoneCurLink + '">' + (copyZoneCurLink + 1) + '</a>';
copyZoneCurLink++;
num_of_pagination_shown++;
}
copyZoneHtml += '<a class="page_link" id="btnNextZoneSet" longdesc="' + copyZoneCurLink + '">...</a>';
}
else {
while (copyZonePages > copyZoneCurLink) {
copyZoneHtml += '<a class="page_link_clicked" longdesc="' + copyZoneCurLink + '">' + (copyZoneCurLink + 1) + '</a>';
copyZoneCurLink++;
}
}
$(groupUl).parent().parent().find('ul li.footer').html(copyZoneHtml);
$('.page_link_clicked[longdesc=0]').addClass('current');
},
error: function(err) {
var err = eval("(" + err.responseText + ")");
if (ShowModalLogin(err.ExceptionType)) {
alert("An error occurred.");
}
}
});
});
after doing more test i see that post is actually being repeated numberous times.
http://api.jquery.com/live/ states that
To stop further handlers from executing after one bound using .live(), the handler must return false. Calling .stopPropagation() will not accomplish this.
I am not sure if that applies here, but you could add a
return false;
at the end of your click handler and see if it works.

Categories