I have a method in code behind which downloads a file from server to the client. And after that I want to run a javascript function. But it does not work. It works only if the javascript function is in the button click event.
string imageFilePath = Server.MapPath("~/TireLabel.png");
Bitmap bitmap = (Bitmap)Image.FromFile(imageFilePath);//load the image file
Graphics g = Graphics.FromImage(bitmap);
string text = "215/45 R 20";
g.DrawString(text, drawFontArial26Bold, drawBrush, new RectangleF(x, y, width, height), drawFormatCenter);
text = "013";
g.DrawString(text, drawFontArial20Regular, drawBrush, new RectangleF(70, 45, 0, 0), drawFormatRight);
text = "1";
g.DrawString(text, drawFontArial20Regular, drawBrush, new RectangleF(100F, 80, 0, 0), drawFormatRight);
text = "2";
g.DrawString(text, drawFontArial20Regular, drawBrush, new RectangleF(240, 80, 0, 0), drawFormatRight);
Bitmap bit = new Bitmap(bitmap);
bit.Save(Server.MapPath("~/TireLabel.bmp"), System.Drawing.Imaging.ImageFormat.Bmp);
Response.ContentType = "application/jpeg";
Response.AddHeader("content-disposition", "attachment; filename=" + Server.MapPath("~/TireLabel") + ".bmp");
Response.WriteFile(Server.MapPath("~/TireLabel.bmp" + ""));
ClientScript.RegisterStartupScript(GetType(), "key", "runPrint();", true); // THIS does not fire.
//Javascript function
function runPrint() {
var objShell = new ActiveXObject("WScript.Shell");
var strCommand = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";
//var strCommand = "C:\\PrintLabel.exe";
objShell.Exec(strCommand);
//objShell.ShellExecute(strCommand, "","","open","1");
}
How I can make the javascript fire.
This is a hard problem, because the browser normally doesn't tell you when a download is finished. Have a look at jQuery.filedownload that allows you to download files through AJAX.
-- Edit --
Here is the code to attach jQuery filedownload to all links with the class "fileDownload":
$(document).on('click', 'a.fileDownload', function() {
$.fileDownload($(this).prop('href'))
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
return false; //this is critical to stop the click event which will trigger a normal file download
});
This assumes that the URL to the controller action is given in the href attribute of the link, and this action returns a file with return File().
The response must also contain a cookie /fileDownload to inform jquery.fileDownload that a successful file download has occured.
//jquery.fileDownload uses this cookie to determine that a file download has completed successfully
response.AppendCookie(new HttpCookie("fileDownload", "true") {
Path = "/"
});
-- Edit 2 - Changed source to show simpler example with less dependendies. Use the .done promise to trigger an action after the download was done
Related
I have a electron application using jszip to create a zip file that the user is then able save. Everything works fine but my problem is my application uses the users download folder. Im guessing its making a temporary file. I've submitted my application to the mac store and they want me to use another location instead of the users downloads folder for the temporary file. Is there anyway I can specify the temporary location or maybe something else other then jszip that will do this?
Here is the code I use
savePNGButton.addEventListener('click', function(e) {
var zip = new JSZip();
if (WatermarkText == ""){
var img = zip.folder("images");
} else {
var img = zip.folder(WatermarkText);
}
$(".WatermarkPhoto").each(function(index) {
imgsrc = this.src;
var DataURL = imgsrc.replace('data:image/png;base64,','');
img.file(WatermarkText+index+".png", DataURL, {base64: true});
});
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, WatermarkText+".zip");
});
});
[edit]
Looking more into this it looks like my problem is not with JSZip but with chrome or FileSaver.js using the downloads folder as a temp folder for the file before the users chooses where to place the file. Is there anyway I can change the temp location for my electron app?
If anyone comes across this, I never figured a way around the HTML5 filesystem way of moving the temp file before the users selects the download location. Instead I am using nodejs file system with electrons showSaveDialog. I also had to change JSZip to use .generateNodeStream instead of .generateAsync. Below is my function that I got working for me.
savePNGButton.addEventListener('click', function(e) {
var zip = new JSZip();
if (WatermarkText == ""){
var img = zip.folder("images");
} else {
var img = zip.folder(WatermarkText);
}
$(".WatermarkPhoto").each(function(index) {
imgsrc = this.src;
var DataURL = imgsrc.replace('data:image/png;base64,','');
img.file(WatermarkText+index+".png", DataURL, {base64: true});
});
// zip.file("file", content);
// ... and other manipulations
dialog.showSaveDialog({title: 'Test',defaultPath: '~/'+WatermarkText+'.zip',extensions: ['zip']},(fileName) => {
if (fileName === undefined){
console.log("You didn't save the file");
return;
}
zip
.generateNodeStream({type:'nodebuffer',streamFiles:true})
.pipe(fs.createWriteStream(fileName))
.on('finish', function () {
// JSZip generates a readable stream with a "end" event,
// but is piped here in a writable stream which emits a "finish" event.
console.log("zip written.");
});
});
});
I have a really strange behiavour with the loading of a SWF file: the buttons on it are working on the first load, but if I reload the page they don't work anymore, even if I empty my cache or force SWF reload by appending a random parameter at the end of the URL. The buttons are generated from a XML file called in the init function.
Here is how I call my swf :
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script
<script type="text/javascript">
// <![CDATA[
window.onload=function(){
var _time = (new Date()).getTime();
var params = {wmode: "transparent", src: "http://www.mywebsite.com/sites/default/files/medias/map/monde.swf?" + _time};
var flashvars = {site: "/fr"};
swfobject.embedSWF("http://www.mywebsite.com/sites/default/files/medias/map/monde.swf?" + _time, "flashContent", 920, 450, "10", false, flashvars, params);
};
// ]]>
</script>
<div id="flashContent"> </div>
The only way to get the buttons back is to edit the source in Firebug, change the SWF URL with something random and change it back so the URL is loaded again (it's not working on the first try, I have to do it few times before it works).
I don't have any cache on the SWF and on the XML I'm calling from AS3, so I don't understand how I can have such a random behaviour :
Here is the relevant parts of the AS3 script :
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var site:String = "";
if (this.loaderInfo.parameters.site != undefined)
site = this.loaderInfo.parameters.site;
_uLoader = new URLLoader();
_uLoader.addEventListener(Event.COMPLETE, _initMap);
var httpHeader : URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
var httpRequest : URLRequest = new URLRequest(site+"/ajax/mywebsite_tools/list_master");
httpRequest.requestHeaders.push(httpHeader);
httpRequest.method = URLRequestMethod.GET;
httpRequest.data = new URLVariables("time="+Number(new Date().getTime()));
_uLoader.load(httpRequest);
_supportContinent = new MovieClip();
this.addChild(_supportContinent);
}
private function _initMap(e:Event):void
{
var cs:mywebsiteSingleton = mywebsiteSingleton.getInstance();
var xml:XML = new XML(_uLoader.data);
cs.xml = xml;
btRetour.buttonMode = true;
btRetour.mouseChildren = false;
btRetour.txt.text = xml.retour.text();
btRetour.gotoAndStop('OUT');
addEventListener(mywebsiteEvent.CONTINENT_CLICK, _contientClick);
btRetour.addEventListener(MouseEvent.CLICK, _retourMonde);
btRetour.addEventListener(MouseEvent.ROLL_OVER, _over);
btRetour.addEventListener(MouseEvent.ROLL_OUT, _out);
}
Figured it out. It was rather trivial in fact, the _initMap() function was randomly called before or after my buttons appear on the timeline. So if i get the xml too fast, the _initMap() function try to refer to a button that doesn't exist.
Fixed it with something a bit dirty, but anyway it works :
private function _initMap(e:Event):void
{
if(!btRetour || btRetour == null || !btRetour.hasOwnProperty("buttonMode")) {
setTimeout(_initMap, 500, e);
return;
}
// ...
}
I have a webform with a Download LinkButton, on the button's click event I'm fetching data and then generating an .XLSX file for download. During the generation of the file, Response.Clear() is called, Response.ContentType is set and eventually Response.End() is called.
I need to display a spinner .gif during that operation. Once the file has been generated and the file "Open/Save" dialog pops up, the spinner should not display. Unfortunately, since I'm changing the content type and calling Response.End there is no response returned back to the page to work with.
Can anyone please provide a little help with this scenario?
I actually ended up going with a solution that did not require the use of an iFrame. Instead I make use of a Cookie, which the file generation process writes into it simple a Name Value pair. This cookie can then be checked later from the client side via JavaScript to determine when the response (.xlsx file) has completed.
The result should be that the loading spinner image should display until the .xls file has been generated and returned to the client (Cookie contains the DownloadComplete=true Name Value pair).
In the OnClientClick event for the LinkButton:
function startFileDownload(){
// Set Timout for calling checkState function again
setTimeout(checkState, 1100);
setCookie('DownloadComplete', '', 1);
// Download is starting, Hide Download LinkButton
document.getElementById('<%= btnDownloadExcel.ClientID%>').style.display = "none";
// Display progress spinner
var img = document.getElementById("image1");
img.src = "Images/99.GIF";
document.getElementById('image1').className = "spinnerDisplay";
}
Here is the JavaScript code for the checkState function:
function checkState()
{
var img = document.getElementById("image1");
var finished = getCookie("DownloadComplete");
// Check to see if download is complete
if (!isEmpty(finished)) {
setCookie('DownloadComplete', '');
// Download is complete, Hide progress spinner
img.className = "spinnerHide";
document.getElementById('<%= btnDownloadExcel.ClientID%>').style.display = "";
} else {
// Refresh progress spinner, Set Timout for calling checkState function again
img.src = "Images/99.GIF";
setTimeout(checkState, 1100);
}
}
Here is the JavaScript code for the setCookie and the getCookie functions:
function setCookie(cName, value){
var now = new Date();
var time = now.getTime();
time += 3600 * 1000;
now.setTime(time);
document.cookie = cName + "=" + value
+ '; expires=' + now.toGMTString() + '; path=/';
}
function getCookie(cName)
{
var i, x, y, ARRcookies = document.cookie.split(";");
for (i = 0; i < ARRcookies.length; i++) {
x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
x = x.replace(/^\s+|\s+$/g, "");
if (x == cName) {
return unescape(y);
}
}
}
Then on the server side in the class that generates the .xlsx file, after clearing the HTTP Response add a Name Value pair to the Cookie:
HttpContext.Current.Response.Clear();
// Append a cookie that will tell the browser the file has finished processing
// and is included in that stream (note specific path must match same path for cookie set in JavaScript)
HttpCookie cookie = new HttpCookie("DownloadComplete", "true");
cookie.Expires = DateTime.Now.AddMinutes(60);
cookie.Path = "/";
HttpContext.Current.Response.AppendCookie(cookie);
//Other code here to specify the MIME type, setup the HTTP header
//and Response.BinaryWrite out the file
HttpContext.Current.Response.End();
It should go like this : (one solution among others)
1) create an iframe on your page which will actually download your file ( so your main page wont be blank )
2) Add a cookie to the response. via
Response.AddHeader("content-disposition", "attachment;filename=1.jpg");
3) when a user press "download" you set (via js) the src for the iframe to download the file. and you show the spinner. after this , you start reading via setInterval , if theres a cookie. if thereis - the download has finished so you can hide the spinner.
I am using jspdf to generate a pdf file. Every thing is working fine. But how to open generated
pdf in new tab or new window.
I am using
doc.output('datauri');
Which is opening the pdf in same tab.
Based on the source you can use the 'dataurlnewwindow' parameter for output():
doc.output('dataurlnewwindow');
Source in github:
https://github.com/MrRio/jsPDF/blob/master/jspdf.js#L914
All possible cases:
doc.output('save', 'filename.pdf'); //Try to save PDF as a file (not works on ie before 10, and some mobile devices)
doc.output('datauristring'); //returns the data uri string
doc.output('datauri'); //opens the data uri in current window
doc.output('dataurlnewwindow'); //opens the data uri in new window
This solution working for me
window.open(doc.output('bloburl'))
I have to use this to load the PDF directly. Using doc.output('dataurlnewwindow'); produces an ugly iframe for me. Mac/Chrome.
var string = doc.output('datauristring');
var x = window.open();
x.document.open();
x.document.location=string;
this code will help you to open generated pdf in new tab with required title
let pdf = new jsPDF();
pdf.setProperties({
title: "Report"
});
pdf.output('dataurlnewwindow');
Or...
You can use Blob to achive this.
Like:
pdf.addHTML($('#content'), y, x, options, function () {
var blob = pdf.output("blob");
window.open(URL.createObjectURL(blob));
});
That code let you create a Blob object inside the browser and show it in the new tab.
Search in jspdf.js this:
if(type == 'datauri') {
document.location.href ='data:application/pdf;base64,' + Base64.encode(buffer);
}
Add :
if(type == 'datauriNew') {
window.open('data:application/pdf;base64,' + Base64.encode(buffer));
}
call this option 'datauriNew' Saludos ;)
using javascript you can send the generated pdf to a new window using the following code.
var string = doc.output('datauristring');
var iframe = "<iframe width='100%' height='100%' src='" + string + "'></iframe>"
var x = window.open();
x.document.open();
x.document.write(iframe);
x.document.close();
This is how I handle it.
window.open(doc.output('bloburl'), '_blank');
Generally you can download it, show, or get a blob string:
const pdfActions = {
save: () => doc.save(filename),
getBlob: () => {
const blob = doc.output('datauristring');
console.log(blob)
return blob
},
show: () => doc.output('dataurlnewwindow')
}
STEP 1
Turn off addblock
STEP 2
Add
window.open(doc.output('bloburl'), '_blank');
Or try
doc.output('dataurlnewwindow')
Javascript code
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(doc.output("blob"), "Name.pdf");
} else {
// For other browsers:
// Create a link pointing to the ObjectURL containing the blob.
doc.autoPrint();
window.open(
URL.createObjectURL(doc.output("blob")),
"_blank",
"height=650,width=500,scrollbars=yes,location=yes"
);
// For Firefox it is necessary to delay revoking the ObjectURL
setTimeout(() => {
window.URL.revokeObjectURL(doc.output("bloburl"));
}, 100);
}
This works for me!!!
When you specify window features, it will open in a new window
Just like :
window.open(url,"_blank","top=100,left=200,width=1000,height=500");
Step I: include the file and plugin
../jspdf.plugin.addimage.js
Step II: build PDF content
var doc = new jsPDF();
doc.setFontSize(12);
doc.text(35, 25, "Welcome to JsPDF");
doc.addImage(imgData, 'JPEG', 15, 40, 386, 386);
Step III: display image in new window
doc.output('dataurlnewwindow');
Stepv IV: save data
var output = doc.output();
return btoa( output);
Javascript code: Add in end line
$("#pdf_preview").attr("src", pdf.output('datauristring'));
HTML Code: Insert in body
<head>
</head>
<body>
<H1>Testing</h1>
<iframe id="pdf_preview" type="application/pdf" src="" width="800" height="400"></iframe>
</body>
</html>
preview within same window inside iframe along with with other contents.
Additionally, it is important to remember that the output method has other values and it might be interesting to test all of them to choose the ideal one for your case.
https://artskydj.github.io/jsPDF/docs/jsPDF.html#output
test one line at a time:
doc.output('arraybuffer');
doc.output('blob');
doc.output('bloburi');
doc.output('bloburl');
doc.output('datauristring');
doc.output('dataurlstring');
doc.output('datauri');
doc.output('dataurl');
doc.output('dataurlnewwindow');
doc.output('pdfobjectnewwindow');
doc.output('pdfjsnewwindow');
I am using jquery's Uploadify to upload images on server. Now what i am doing when user successfully upload a image, i want to replace this image with the old one. for that i am binding the image onsuccess method of uploadify, it is working fine if the image's name is always different then the previous one, but if the image's name is same as the old one it not refreshing the image, its still showing the old image.here is my code:
var WishId = "";
var ImagePath = $('[id$=hdnImgPath]').val();
var DefaultImagePath = $('[id$=hdnDefaultImagePath]').val();
$("[id$=fpFiles]").uploadify({
'swf': 'Swf/uploadify.swf',
'uploader': 'Resources/Handlers/UploadProfilePic.ashx',
'progressData': 'speed',
'cancelImg': 'Images/Grid_ActionDelete.gif',
'fileSizeLimit': '1MB',
'fileTypeExts': '*.gif; *.jpg; *.png',
'auto': true,
'multi': false,
'buttonText': 'Select',
'onSelect': function () {
WishId = $('[id$=hdnWishId]').val();
$('#lnkUpload' + WishId).show(250);
},
'onUploadStart': function (file) {
$("[id$=fpFiles]").uploadify('settings', 'formData', { 'WishID': "'" + WishId + "'" });
},
'onUploadSuccess': function (file, data, response) {
data = data.replace('"', '').replace('"', '');
if (data != '') {
alert(data);
$('[id$=imgUsersProfilePic]').attr('src', ImagePath + data);
// $('#hdnImageName' + WishId).val(data);
} else {
$('#img' + WishId).attr('src', DefaultImagePath + 'defaultProfile.png');
}
}
});
Please let me know what i have to do to display the latest image without post back, one thing more when i refresh my page its displaying the latest image.let me know where am i wrong.
Update: i know this image is coming from cache but i cannot delete the cache, if i it will delete users session too. so i need some alternate...
You can add a random number at the end of the image right after you show it there, so at the moment is still loading and work with it, is always force to load it again.
$('[id$=imgUsersProfilePic]')
.attr('src', ImagePath + data + '?' + Math.random());
You can try versioning the images once you change them.
Eg: for defaultProfile.png, replace it with defaultProfile.png?v=1 in the javascript code. This will fetch the latest image from the server and not from the cache.