I have successfully set up using the viewer with the following code:
protected void btnShowPDFS_OnClick(object sender, EventArgs e)
{
// Display all files.
string[] files = Directory.GetFiles(#"D:\Reports\2014\July\", "*.PDF");
var pdfNames = new List<string>();
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string queryString = "/web/viewer.html?file=" + System.Web.HttpUtility.UrlEncode("../July/" + fileName);
pdfNames.Add(queryString);
}
listView.DataSource = pdfNames;
listView.DataBind();
}
Now, this all works fine if all my PDF's are in a folder within the website (i.e localhost). However, how do i point the view to either a network share, or just another folder on the same machine, but outside of IIS?
A browser's XMLHttpRequest might have a restrictions for local files access (Firefox has more relaxed policy for local file than other browsers).
PDF.js is using XHR; and PDF.js also allows "load" files from a typed array (Uint8Array). You can use the latter in your solution. Notice the Internet Explorer (WebBrowser control) has window.external that can be used to transmit the data from the host application, see http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting(v=vs.110).aspx
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.
With Asp.NET Core, The handy path-finding functions in Environment are gone. HttpContext and HttpServerUtility have been stripped. And the Application store within the Cache framework is gone. I can no longer assume (in code) that my server is using IIS or that it's even running on a Windows box.
And I don't have a database; I have a set of JSON files. Which, for reasons outside the scope of this question, cannot be stored in a database.
How do I read and write to files on the server?
In the new ASP.NET Core world when we deploy we have 2 folders appRoot and wwwroot
we generally only put files below the wwwroot folder that we intend to serve directly with http requests. So if your json files are to be served directly ie consumed by client side js then maybe you would put them there, otherwise you would use a different folder below appRoot.
I will show below how to resolve paths for both scenarios, ie sample code how to save a json string to a folder below either appRoot or wwwroot. In both cases think of your location as a virtual path relative to one of those folders, ie /some/folder/path where the first / represents either appRoot or wwwroot
public class MyFileProcessor
{
public MyFileProcessor(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
hostingEnvironment = env;
appEnvironment = appEnv;
appRootFolder = appEnv.ApplicationBasePath;
}
private IHostingEnvironment hostingEnvironment;
private IApplicationEnvironment appEnvironment;
private string appRootFolder;
public void SaveJsonToAppFolder(string appVirtualFolderPath, string fileName string jsonContent)
{
var pathToFile = appRootFolder + appVirtualFolderPath.Replace("/", Path.DirectorySeparatorChar.ToString())
+ fileName;
using (StreamWriter s = File.CreateText(pathToFile))
{
await s.WriteAsync(jsonContent);
}
}
public void SaveJsonToWwwFolder(string virtualFolderPath, string fileName string jsonContent)
{
var pathToFile = hostingEnvironment.MapPath(virtualFolderPath) + fileName;
using (StreamWriter s = File.CreateText(pathToFile))
{
await s.WriteAsync(jsonContent);
}
}
}
Silly question but here goes...
Is it possible to write an intranet windows auth asp.net mvc app that uses File.Move to rename a file on a users machine? Or will the File.Move and using Path.GetDirectory and other System.IO functions look on the IIS server directory structure instead of the client machine?
[HttpPost]
public ActionResult Index(HttpPostedFileBase file, string append)
{
try
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
DirectoryInfo filepath = new DirectoryInfo(file.FileName);
string parentpath = Path.GetDirectoryName(filepath.FullName);
DirectoryInfo searchablePath = new DirectoryInfo(parentpath);
var directories = searchablePath.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo d in directories)
{
if (!string.IsNullOrEmpty(append) && !d.Name.Contains(append))
{
string fName = Path.GetFileNameWithoutExtension(d.Name);
string fExt = Path.GetExtension(d.Name);
System.IO.File.Move(d.FullName, Path.Combine(d.DirectoryName, fName + append + fExt));
}
}
}
}
catch (Exception ex)
{
}
return View();
}
I have tried this but am getting a filenotfoundexception.
Any ideas?
The ASP.NET code runs on the server, so it will look at the files on the server.
You can't rename a file on the client machine, however it would be possible to rename a file on the computer that is used as client, if:
the server and computer are on the same network
the server knows the name of the computer
the server knows which folder to look for in the computer
the folder is shared with the user account running the ASP.NET code on the server with enough privileges to change the name of a file
In that sense the computer is not a client to the server, but the server communicates directly with the computer via the file system, not via IIS.
These will indeed work only on the server.
You may look at the various file and filesystem related specifications for client-side javascript APIs provided by the user's browser:
http://www.w3.org/TR/FileAPI/
http://www.w3.org/TR/file-system-api/
http://www.w3.org/TR/file-writer-api/
I have a MVC application. I need to open the pdf file when user clicks the open button on the page. The filepath where the pdf is stored is read from the database and it is a file on c:. How do I open it in my html code? I have this code:
Open
but this doesn't open my file. What do I have to do? I need to specify somewhere that it is a pdf??
You will need to provide a path to an action that will receive a filename, resolve the full path, and then stream the file on disk from the server to the client. Clients out in the web, thankfully, cannot read files directly off your server's file system (unless... are you suggesting #Model.CertificatePath is the path to the file on the remote user's machine?).
public ActionResult Download(string fileName)
{
string path = Path.Combine(#"C:\path\to\files", fileName);
return File(path, "application/pdf");
}
Update
If #Model.CertificatePath is the location on the client's actual machine, try:
Open
Note that some browsers may have security settings disallowing you from opening local files.
Try like this in your View
#Html.ActionLink("View", "ViewPDF", new { target = "_blank" })
Now Link will open in new window. You can write the pdf bytes in ViewPDF controller method
You could have the link fire a method such as the one below which will then stream your chosen file to the file download rather than opening the pdf in the broswer.
/// <summary>
/// Forces a file to be displayed to the user for download.
/// </summary>
/// <param name="virtualPath"></param>
/// <param name="fileName"></param>
public static void ForceDownload(string virtualPath, string fileName)
{
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.AddHeader("content-disposition", "attachment; filename=" + fileName);
response.WriteFile(virtualPath);
response.ContentType = "";
response.End();
}
Well if your getting the path value and the value is in #Model.CertificatePath
this wiil not work
Open
You will need to add this
Open
and make sure you path is relative by adding this ~
for example if your path is /Content/pdfs/CertificatePath.pdf
it would need to look like
~/Content/pdfs/CertificatePath.pdf
This should be the simplest way to make it work.
Hope this helps.
Unfortunately you can't dictate where the PDF will be opened, mainly because you can't guarantee the Adobe Acrobat reader plugin is installed or how it functions.
You could in theory open a new window, and in that new window have a JavaScript function to open the PDF file, but again you can't guarantee it will open in a embedded window without the plugin, the best you can hope for is "best try".
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