Open PDF in new Tab - Blazor - html

I would like to open a PDF in a new Tab. The following code works in a normal HTML File, but not in Blazor. Is there any way to use it in Blazor or is there another way to open a PDF in Blazor?
Read more

What works in "normal" HTML, does not work in Blazor, because the service-worker routes unknown routes to index.html. See onFetch() method of service-worker.published.js:
const shouldServeIndexHtml = event.request.mode === 'navigate';
const request = shouldServeIndexHtml ? 'index.html' : event.request;
When you click your link Read more, the shouldServeIndexHtml is true.
To avoid this, simply change above code to
const shouldServeIndexHtml = event.request.mode === 'navigate'
&& !event.request.url.includes('/pdf/');
const request = shouldServeIndexHtml ? 'index.html' : event.request;
This assumes, that your pdfs are in a subfolder "pdf" under wwwroot. Please find more information here. Since the url includes "/pdf/", the shouldServeIndexHtml becomes false and your pdf is displayed.

Two options I can suggest:
Via a button.
#inject IJSRuntime jsRuntime
<button #onclick="#LoadPage">Load Page</button>
#code {
async Task LoadPage()
{
await jsRuntime.InvokeAsync<object>("open", "MyPage", "_blank");
}
}
Via a link.
<a class="dropdown-item" href="MyPage" target="_blank">
where the razor page you want to launch has the following at the top:
#page "/MyPage"

Related

Cypress e2e testing: How to access new tab by clicking on "href". I don't have target attribute to remove and test on new opened tab?

This attached image is my HTML code for href which will open a new tab
The DOM has iframe so I wrote below code accessed the href and it will open in new tab. I am unable to access the newly opened tab, though I know the method that would have target attribute so we remove that and open in same tab but here I don't have any target attributes.
Please check this and help to access my new tab.
cy.visit('https://yopmail.com/en/')
cy.get('.ycptinput').type('some_name {enter}')
cy.wait(2000)
cy.get('#ifmail').its('0.contentDocument.body').then(cy.wrap).find('a').click()
The cy.origin() command is meant to solve the "new tab" problem.
It's a bit new, so expect some teething problems. Basically, it sets up a sand-boxed domain that can use Cypress commands.
Anything from outside cy.origin() that you want to use inside (for example, the link you found) needs special handling to pass in.
It gets passed in on a special args option, and is received in the same pattern.
let link;
cy.visit('https://yopmail.com/en/')
cy.get('.ycptinput').type('some_name {enter}')
cy.wait(2000)
cy.get('#ifmail').its('0.contentDocument.body')
.then($body => {
link = $body.find('a')[0].href
})
cy.then(() => { // this just waits for above block to complete
const newOrigin = link.split('?')[0] // remove query params
.replace('http://', 'https://') // correct for secure protocol
cy.origin(newOrigin, { args: { link } }, ({ link }) => {
cy.visit(link) // same as ".find('a').click()" but works cross-domain
})
})

Downloading files using vue.$http not working on chrome mobile

I have a function in my vue that I use to download files from the firebase cloud storage. The functions look like:
forceFileDownload(response, issue, index){
const increment = firebase.firestore.FieldValue.increment(1)
db.collection('issues').doc(this.ids[index]).update({
downloads: increment
})
var extension = mimeTypes.extension(response.headers['map']['content-type'][0]);
const url = window.URL.createObjectURL(new Blob([response.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', issue['name']+"."+extension) //or any other extension
document.body.appendChild(link)
link.click()
},
downloadWithVueResource(issue, index) {
this.$http({
method: 'get',
url: issue['path'],
responseType: 'arraybuffer'
})
.then(response => {
this.forceFileDownload(response, issue, index)
})
.catch(() => console.log('error occured'))
},
As you can see above I am using vue-resource to download the file. The reason I am doing this instead of binding the link to an anchor tag is because the file is dynamically rendered using a v-for as follows:
<div v-for="(issue, index) in issues" :key="index">
<button #click="downloadWithVueResource(issue, index)">Download</button>
</div>
This works fine on my ubuntu chrome and on safari on my phone. But it's not working in chrome on my phone. I don't understand why this is happening. Any help would be appreciated. Thanks
You can check Chrome Download Attribute not working for potential solutions for the download attribute. You can also check what version you have and whether it supports the download attribute here.
You said that the reason you're using vue-resource is because
The reason I am doing this instead of binding the link to an anchor tag is because the file is dynamically rendered using a v-for
You should be able to use an anchor tag. The only reasons (that I'm aware of) that you can't use an anchor tag for downloads are if there's some authentication on your backend that looks at an authorization header for example or you would want to do some custom javascript, like a progress bar for example.
You can bind the href to your path property.
<div v-for="(issue, index) in issues" :key="index">
<a :href="issue.path" #click="logDownload(issue, index)">Download</a>
</div>
Then log the download on click:
logDownload(issue, index)
{
const increment = firebase.firestore.FieldValue.increment(1);
db.collection('issues').doc(this.ids[index]).update({
downloads: increment
});
}

angularjs download file via POST on IE8/9 without page refresh

I'm trying to download a dynamically generated file from the server using a hidden form.
Below is the angular function that I'm using to submit the hidden form
$scope.downloadCsv = function() {
var dataset = JSON.stringify($scope.dataset);
var body = $('body');
var reportParamJson = angular.toJson($scope.dataset);
var hiddenForm = "<form action='/Reports/SaveTestCsv' method='POST' target='_blank'><input type='hidden' name='dataset' value='" + dataset + "'/ ><button id='submitCSV' type='submit'></button></form>";
body.append(hiddenForm);
$('#submitCSV').click();
}
Below is the .net mvc method to generate the response with the file
[HttpPost]
public ActionResult SaveTestCsv(string dataset)
{
var data = JsonConvert.DeserializeObject<MyObject>(dataset);
var binary = getTestCSV(data);
var file = File(binary, "text/csv", "test.csv");
return file;
}
Below is the relevant html code from the partial html page that I'm including in the view using ng-include
<div>Download CSV</div>
<div ng-grid="gridOptions"></div>
.
When I click on "Download CSV", Chrome, FF and IE10 prompts me to save the file without refreshing the page/view, but on IE8/9, the page is refreshed, so the content from the ng-include tag is gone, in particular the html I posted above is no longer present.
I'm wondering if this has something to do with the hashbang in the url from IE8/9 and is there any way to fix this?
Edit
I ended up removing routing from angular completely and just use .net MVC to do the routing for me, and then it's working on IE8

Chrome addon with my server interaction

its many days reading hundreds of ways to help me make what I really need. No success at all.
What I need is this:
1) Having a button which only works when the tab has a certain url.
2) After clicking it, must read page's source and then get some pieces of it to send them to my server page in order to check my database for recordcounts (I assume with AJAX & javascript). Then this page should send back to the extension its responses and populate the popup html.
Looks easy I know, but please I need the workflow if not the required codes for the extension.
Thank you so much!
ok so you can chceck selected tab and it's url with:
chrome.tabs.getSelected(null,function(tab) {
workWithUrl(tab.url);
});
...
function workWithUrl(url){
if (url == ...
...
}
To be able to chceck this you need to add permission for "tabs"
To process page source code, send it to web service and change popup.html:
var xhr = new XMLHttpRequest();
xhr.open("POST", "__server adress___", true);
//headers
xhr.setRequestHeader("Content-Type", "application/json");
//response
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
//response from service to popup.html
document.body.innerHTML = xhr.responseText;
}
}
//process page here
xhr.send(pageText);
You have to add permission for server adress to manifest as well and everything should be executed from popup.js (or html).

The right way of setting <a href=""> when it's a local file

I'm trying to link to a local file. I've set href as follows:
Link Anchor
In Firefox, when I right click and "open link in new tab", nothing happens.
When I right click and "copy link location", then manually open a new tab and paste the copied link, it works fine. So it seems my file:// syntax is fine. I've also tried it with 3 slashes like file:/// but it's the same result.
What am I doing wrong?
By definition, file: URLs are system-dependent, and they have little use. A URL as in your example works when used locally, i.e. the linking page itself is in the user’s computer. But browsers generally refuse to follow file: links on a page that it has fetched with the HTTP protocol, so that the page's own URL is an http: URL. When you click on such a link, nothing happens. The purpose is presumably security: to prevent a remote page from accessing files in the visitor’s computer. (I think this feature was first implemented in Mozilla, then copied to other browsers.)
So if you work with HTML documents in your computer, the file: URLs should work, though there are system-dependent issues in their syntax (how you write path names and file names in such a URL).
If you really need to work with an HTML document on your computers and another HTML document on a web server, the way to make links work is to use the local file as primary and, if needed, use client-side scripting to fetch the document from the server,
Organize your files in hierarchical directories and then just use relative paths.
Demo:
HTML (index.html)
<a href='inner/file.html'>link</a>
Directory structure:
base/
base/index.html
base/inner/file.html
....
The href value inside the base tag will become your reference point for all your relative paths and thus override your current directory path value otherwise - the '~' is the root of your site
<head>
<base href="~/" />
</head>
This can happen when you are running IIS and you run the html page through it, then the Local file system will not be accessible.
To make your link work locally the run the calling html page directly from file browser not visual studio F5 or IIS simply click it to open from the file system, and make sure you are using the link like this:
Intro
../htmlfilename with .html
User can do this
This will solve your problem of redirection to anypage for local files.
Try swapping your colon : for a bar |. that should do it
Link Anchor
The right way of setting a href=“” when it's a local file.
It will not make any issue when code or file is online.
FAQ
Hope it will help you.
Here is the alternative way to download local file by client side and server side effort:
<a onclick='fileClick(this)' href="file://C:/path/to/file/file.html"/>
Js:
function fileClick(a) {
var linkTag = a.href;
var substring = "file:///";
if (linkTag.includes(substring)) {
var url = '/cnm/document/v/downloadLocalfile?path=' + encodeURIComponent(linkTag);
fileOpen(url);
}
else {
window.open(linkTag, '_blank');
}
}
function fileOpen(url) {
$.ajax({
url: url,
complete: function (jqxhr, txt_status) {
console.log("Complete: [ " + txt_status + " ] " + jqxhr);
if (txt_status == 'success') {
window.open(url, '_self');
}
else {
alert("File not found[404]!");
}
// }
}
});
}
Server side[java]:
#GetMapping("/v/downloadLocalfile")
public void downloadLocalfile(#RequestParam String path, HttpServletResponse
response) throws IOException, JRException {
try {
String nPath = path.replace("file:///", "").trim();
File file = new File(nPath);
String fileName = file.getName();
response.setHeader("Content-Disposition", "attachment;filename=" +
fileName);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
response.setStatus(200);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
// out.flush();
in.close();
out.close();
}
else {
response.setStatus(404);
}
} catch (Exception ex) {
logger.error(ex.getLocalizedMessage());
}
return;
}