Downloading files in an SDK add-on - javascript

There are so much topics about download files with addon sdk, but I try to deal with the problem from since few days and still I got nothing...
Ok, I work on AddOn Builder online on FireFox and I want get something like this:
Link with pdf -> I click on this by right mouse button -> chosing the "Get PDF" -> pdf is downloading to f.e. "c:\temp\"
I founded many of example codes, but every code doesn't work.
I don't have any errors, everything built ok, but when I clicked the "Get PDF" nothing saved in "c:\temp\" folder.
Every code is similar so i paste two of them:
This is my exports.main = function()
const { Cc, Ci, Cu } = require('chrome');
var contextMenu = require("sdk/context-menu");
var menuItem = contextMenu.Item({
label: "Get PDF",
context: contextMenu.SelectorContext(" a[href *= '.pdf']"),
contentScript: 'self.on("click", function (node, data) {' +
' self.postMessage("test.pdf", "link to pdf");' +
'});',
onMessage: function (sLocalFileName, sRemoteFileName)
{
var saveToDirectory = 'C:\\temp\\';
//var chrome = require("chrome");
var oIOService = Cc["#mozilla.org/network/io-service;1"].getService(Ci.nsIIOService)
var oLocalFile = Cc["#mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
oLocalFile.initWithPath(saveToDirectory + sLocalFileName);
var oDownloadObserver = {onDownloadComplete: function(nsIDownloader, nsresult, oFile) {console.log('download complete...')}};
var oDownloader = Cc["#mozilla.org/network/downloader;1"].createInstance();
oDownloader.QueryInterface(Ci.nsIDownloader);
oDownloader.init(oDownloadObserver, oLocalFile);
var oHttpChannel = oIOService.newChannel(sRemoteFileName, "", null);
oHttpChannel.QueryInterface(Ci.nsIHttpChannel);
oHttpChannel.asyncOpen(oDownloader, oLocalFile);
}
});
Second:
const { Cc, Ci, Cu } = require('chrome');
var contextMenu = require("sdk/context-menu");
var menuItem = contextMenu.Item({
label: "Get PDF",
context: contextMenu.SelectorContext(" a[href *= '.pdf']"),
contentScript: 'self.on("click", function (node, data) {' +
' self.postMessage(node.href);' +
'});',
onMessage: function (links)
{
// download from: aURLToDownload
var downloadURI = Cc["#mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newURI(links, null, null);
// download destination
var outputFile = Cc["#mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
outputFile.initWithPath("c:\\temp\\1.pdf");
var persist = Cc["#mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
persist.saveURI(downloadURI, null, null, null, "", outputFile);
}
});
Please help!

Alright I had a similar issue when I was playing around with this.. My code is very close to what you have but I added a few helpful steps.. First I get the directory path from preferences. Then I actually create the directory if it does not exist.. In my case I was creating sub-directories as well, you may not need it but just in case.
function DownloadFile(sdirectory, sLocalFileName, sRemoteFileName)
{
var baseDirectory = require('sdk/simple-prefs').prefs['downloadpath'] + "\\";
var saveToDirectory = baseDirectory + sdirectory + '\\';
var oLocalDir = chrome.Cc["#mozilla.org/file/local;1"].createInstance(chrome.Ci.nsILocalFile);
oLocalDir.initWithPath(saveToDirectory);
if(!oLocalDir.exists())
{
oLocalDir.create(1,777);
}
var oIOService = chrome.Cc["#mozilla.org/network/io-service;1"].getService(chrome.Ci.nsIIOService)
var oLocalFile = chrome.Cc["#mozilla.org/file/local;1"].createInstance(chrome.Ci.nsILocalFile);
oLocalFile.initWithPath(saveToDirectory + sLocalFileName);
var oDownloadObserver = {onDownloadComplete: function(nsIDownloader, nsresult, oFile)
{
console.log('download complete...');
}};
var oDownloader = chrome.Cc["#mozilla.org/network/downloader;1"].createInstance();
oDownloader.QueryInterface(chrome.Ci.nsIDownloader);
oDownloader.init(oDownloadObserver, oLocalFile);
var oHttpChannel = oIOService.newChannel(sRemoteFileName, "", null);
oHttpChannel.QueryInterface(chrome.Ci.nsIHttpChannel);
oHttpChannel.asyncOpen(oDownloader, oLocalFile);
}
First thing you should do if you have not already, go to about:config and change devtools.errorconsole.enabled to true.
Next add a log statement to the beginning of your download event.. I would actually suggest you break out that method and just call the DownloadFile method in you event.
The most important thing I found out I had to do was sanitize my file name.. with
var file = "somefilename"
file = file.replace(/[/\\:?<>|\"]+/g, "");
If the file name with illegal characters, or a directory path wrong at all I had the same issues.
So I would make your code like..
....
onMessage: function (filename, fileURL)
{
console.log("Message Event, filename: " + filename +" URL: " +fileURL);
DownloadFile(filename,fileURL);
}});
function DownloadFile(sLocalFileName, sRemoteFileName)
{
var baseDirectory = require('sdk/simple-prefs').prefs['downloadpath'] + "\\";
var saveToDirectory = baseDirectory;
var oLocalDir = chrome.Cc["#mozilla.org/file/local;1"].createInstance(chrome.Ci.nsILocalFile);
oLocalDir.initWithPath(saveToDirectory);
if(!oLocalDir.exists())
{
oLocalDir.create(1,777);
}
var oIOService = chrome.Cc["#mozilla.org/network/io-service;1"].getService(chrome.Ci.nsIIOService)
var oLocalFile = chrome.Cc["#mozilla.org/file/local;1"].createInstance(chrome.Ci.nsILocalFile);
oLocalFile.initWithPath(saveToDirectory + sLocalFileName);
var oDownloadObserver = {onDownloadComplete: function(nsIDownloader, nsresult, oFile) {console.log('download complete...')}};
var oDownloader = chrome.Cc["#mozilla.org/network/downloader;1"].createInstance();
oDownloader.QueryInterface(chrome.Ci.nsIDownloader);
oDownloader.init(oDownloadObserver, oLocalFile);
var oHttpChannel = oIOService.newChannel(sRemoteFileName, "", null);
oHttpChannel.QueryInterface(chrome.Ci.nsIHttpChannel);
oHttpChannel.asyncOpen(oDownloader, oLocalFile);
}
EDIT :
Forgot to mention you need this in your package.json file, to be able to set and retrieve the preferences.
"preferences": [{
"name": "downloadpath",
"title": "Download Path",
"description": "Select a directory to download",
"type": "directory"
}]

Related

How to change qr code filename while downloading the file using html.twig and javascript

I have a qr-code button. On click, qr-code is generated and dialog to save the image format pops-up. In which the filename always comes as "qrcode.png". I have to dynamically change the filename to the name of the files from where the qr-code is generated.
Please, help. I am new to this technology.
HTML TWIG
<th data-field="QR-BTN" data-width="60px" data-orderable="false">{{ 'QR'|trans }}</th>
JAVASCRIPT
var QREXPORT = (function() {
var qrCodeExport = function (e){
e.preventDefault();
//goqr.me api url
const QRCODE_API_URL = "https://api.qrserver.com/v1/create-qr-code/?"; //Library Used
var $form = $('#modal-qr-export-offering'),
qrFormat = $("input[name='qrCodeType']:checked").val(),
jsFormData = $form.data('bs.modal'),
accessCode = jsFormData.options.accesscode;
var params = {
data: "SESSION-" + accessCode,
size: "250x250",
margin: 0,
download: 1,
format: qrFormat,
};
window.location.href = QRCODE_API_URL + $.param(params);
};
return {
init: function() {
$(document).ready(function(){
$('#radioSvg').prop('checked', true);
$('#modal-qr-export-offering').on('hidden.bs.modal', function() {
location.reload();
});
});
$(document).on('click', '.js-btn-submit-form', qrCodeExport);
}
};
})();
QREXPORT.init();
Try using the a tag with download attribute...?
const linkEl = document.createElement('a')
linkEl.href = QRCODE_API_URL + $.param(params);
linkEl.download = 'download-name-here.png'
document.body.appendChild(linkEl)
linkEl.click()
// Maybe remove the link after it worked...?
linkEl.remove()

plupload dynamic multipart_params for in progress uploads lost on re-initialization

I have a view in which I initialize a pluploader. I am able to leave this view and still allow the uploads to complete. The problem I am having is that whenever I re-enter the view, and there are uploads that are still in progress, the last multipart_param for "processId" that was assigned within "BeforeUpload" is used repeatedly instead of individually for each file.
Here's an example:
I drop 5 files on the view. I leave the view. Meanwhile 2 files have completed upload progress. The processId for file 1 was "0123" and the processId for file 2 was "0124". I then re-enter the view. This script is ran again. The remaining files are all assigned processId 0124.
I'm sure this is happening because the script is being ran any time you enter the view and something is being overwritten, but I've yet to find a solution.
You can see within the uploader.fileAdded area, that I create a random series of int called a processId with this line
var processId = process.createProcessId(file.index);
Then below, within BeforeUpload, I assign that processId to a multipart_param so that I can assign a unique processId to each upload.
uploader.settings.multipart_params.processId = file.processId;
The Script
/* detects when a user drags files from the desktop */
initDragDetector:function(){
var runtimes = ui.getUploadRunTimes();
var tmpId = Math.random();
uploader = new plupload.Uploader({
runtimes :runtimes,
max_file_size :'500mb',
url :jQuery('#upSrvUrl').val(),
drop_element :'uploadOverlay',
browse_button :'uploadOverlay',
filters : [
{title : "Image files", extensions : "jpg,tif,png,psd"},
],
max_file_count :100,
multipart_params :{rnd_id:Math.random(),tmp_sid:tmpId},
multi_selection :true,
file_data_name :'upfile_0',
});
//INITIALIZATION HANDLER 1
uploader.bind('Init',function(up, params){
uploader.settings.multipart_params.mount = jQuery('#mount').val();
uploader.settings.multipart_params.publisherId = jQuery('#publisherId').val();
uploader.settings.multipart_params.upload_range = 100;
if(uploader.features.dragdrop){
var el = jQuery("#uploadOverlay");
el[0].ondragover = function(event) {
event.dataTransfer.dropEffect = "copy";
};
el[0].ondragenter = function(e) {
if(e.dataTransfer.types.length < 4){
el.show();
}
};
el[0].ondrop = function() {
if(jQuery('.photoThumbContainer').length > 0){
el.hide();
}
};
}
});
//FILES ADDED HANDLER 2 (called after a drop of files)
uploader.bind('FilesAdded', function(up, files){
var i = 0;
plupload.each(files, function(file) {
file.index = i;
uploader.fileAdded(file);
i++;
});
uploader.start();
});
//inject the file into the interface (before before upload function)
uploader.fileAdded = function(file){
var processId = process.createProcessId(file.index);
//added to the file object and passed into the registration
file.processId = processId;
};
//BEFORE EACH UPLOAD HANDLER 3
//Note: this has to be here for any variable passed that changes per file. For example the processId.
uploader.bind('BeforeUpload',function(up,file){
var processId = file.processId;
var photoDiv = jQuery('#photo'+processId+' .photoThumbDiv');
var image = jQuery(new Image()).appendTo(photoDiv);
var preloader = new mOxie.Image();
preloader.downsize(100,100);
preloader.onload = function() {
var img = preloader.getAsDataURL();
jQuery('#photo'+processId+' .photoThumbDiv').html('<img src="'+img+'">');
};
preloader.load(file.getSource());
uploader.settings.multipart_params.processId = file.processId;
});
//PROGRESS HANDLER 4
uploader.bind('UploadProgress',function(up,file){
var processId = file.processId;
var pb = collection.getProgressBar(processId);
if(file.percent<100){
var progress = file.percent;
pb.html('<div class="progressBar"><div class="progressBarColor"> </div></div>');
jQuery('#photo'+processId+' .progressBarColor').css({width:progress+'%'});
}else{
pb.html('<div class="loaderSmall"></div> Processing');
}
});
//FILE FINISHED HANDLER 5
uploader.bind('FileUploaded',function(up,file,info){
var processId = file.processId;
var fileName = file.name;
file.fileName = file.name;
var params = file;
delete params.getNative;
delete params.getSource;
delete params.destroy;
ui.request('registerFile','Photo',params);
//ALL COMPLETE
if(uploadedCnt == up.files.length){
//uploader.splice();
uploader.refresh();
}
});
//GENERAL ERROR HANDLER -
uploader.bind('Error', function(up, err) {
switch(err.code){
case plupload.FILE_EXTENSION_ERROR:
fileExtensions = '';
jQuery.each(up.settings.filters.mime_types,function(index,up) {
if(fileExtensions==''){
fileExtensions=up.extensions;
}else{
fileExtensions+=","+up.extensions;
}
});
var isOrAre = (fileExtensions && fileExtensions.indexOf(',') !== -1) ? 'are':'is';
alertBox.msg("Only "+fileExtensions+" "+isOrAre+" accepted. Please try again.");
break;
case plupload.FILE_SIZE_ERROR:
alertBox.msg("File size can not be larger than "+up.settings.max_file_size+'.');
break;
}
uploader.refresh();
});
uploader.init();
},
Any input is appreciated. Thanks.
If anyone is interested in the solution here, it is because uploader was being set globally. Adding 'var' in front of uploading whenever initializing the uploader fixed it.

Using CKEditor custom filebrowser and upload with ASP.Net MVC

I have a MVC app that Im trying to use CKEditor with. One example I was looking at is here but there are many others. So far so good, but one section im still curious about, is the js that sends the selected file name back to the file upload dialog textbox.
<script type="text/javascript">
$(document).ready(function () {
$(".returnImage").click("click", function (e) {
var urlImage = $(this).attr("data-url");
window.opener.updateValue("cke_72_textInput", urlImage);
window.close();
});
});
</script>
In particular, the cke_72_textInput element. My example wasnt working initially, until I opened chrome dev tools and found the actual id of the textinput, which was in my case cke_76_textInput. Why the id change I wonder? Seems a little "fragile" to refer to a specific id like this? The above js code just takes the selected image file and returns it into the textbox of the fileupload dialog.
Is there something exposed that references this textbox element indirectly without specifying it by id (via the config for example)?
On view:
$(document).ready(function () {
CKEDITOR.replace('Text-area-name', {
filebrowserImageUploadUrl: '/Controller-name/UploadImage'
});
CKEDITOR.editorConfig = function (config) {
// Define changes to default configuration here. For example:
config.language = 'de';
// config.extraPlugins = 'my_own_plugin'; // if you have any plugin
// config.uiColor = '#AADC6E';
// config.image_previewText = CKEDITOR.tools.repeat(' Hier steht dann dein guter Text. ', 8 );
// config.contentsLanguage = 'de';
config.height = 350; // 350px, specify if you want a larger height of the editor
config.linkShowAdvancedTab = false;
config.linkShowTargetTab = false;
};
CKEDITOR.on('dialogDefinition', function (ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
ev.data.definition.resizable = CKEDITOR.DIALOG_RESIZE_NONE;
if (dialogName == 'link') {
var infoTab = dialogDefinition.getContents('info');
infoTab.remove('protocol');
dialogDefinition.removeContents('target');
dialogDefinition.removeContents('advanced');
}
if (dialogName == 'image') {
dialogDefinition.removeContents('Link');
dialogDefinition.removeContents('advanced');
var infoTab = dialogDefinition.getContents('info');
infoTab.remove('txtBorder');
infoTab.remove('txtHSpace');
infoTab.remove('txtVSpace');
infoTab.remove('cmbAlign');
}
});
}
On Contoller:
[HttpPost]
public ActionResult UploadImage(HttpPostedFileBase file, string CKEditorFuncNum, string CKEditor, string langCode)
{
if (file.ContentLength <= 0)
return null;
// here logic to upload image
// and get file path of the image
const string uploadFolder = "Assets/img/";
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath(string.Format("~/{0}", uploadFolder)), fileName);
file.SaveAs(path);
var url = string.Format("{0}{1}/{2}/{3}", Request.Url.GetLeftPart(UriPartial.Authority),
Request.ApplicationPath == "/" ? string.Empty : Request.ApplicationPath,
uploadFolder, fileName);
// passing message success/failure
const string message = "Image was saved correctly";
// since it is an ajax request it requires this string
var output = string.Format(
"<html><body><script>window.parent.CKEDITOR.tools.callFunction({0}, \"{1}\", \"{2}\");</script></body></html>",
CKEditorFuncNum, url, message);
return Content(output);
}
I had the same problem...a little frustrating that I couldn't find any official documentation, considering this seems like a common use case.
Anyways, take a look at the quick tutorial here: http://r2d2.cc/2010/11/03/file-and-image-upload-with-asp-net-mvc2-with-ckeditor-wysiwyg-rich-text-editor/. In case the link ever breaks, here's what I did.
[HttpPost]
public ActionResult UploadImage(HttpPostedFileBase upload, string ckEditorFuncNum)
{
/*
add logic to upload and save image here
*/
var path = "~/Path/To/image.jpg"; // Logical relative path to uploaded image
var url = string.Format("{0}://{1}{2}",
Request.Url.Scheme,
Request.Url.Authority,
Url.Content(path)); // URL path to uploaded image
var message = "Saved!"; // Optional
var output = string.Format("<script>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}');</script>",
CKEditorFuncNum,
url,
message);
return Content(output);
}

Background task for push notifications on Windows Phone 8.1

I'm trying to register a background task on my Windows Phone 8.1 to receive and handle push notifications.At the moment everything is working when the app is opened (foreground+background), but a background task that is defined in the app.js does not work when app is closed.
This is defined in the package.phone.appxmanifest:
<Extension Category="windows.backgroundTasks" StartPage="js/lib/backgroundTask.js">
<BackgroundTasks>
<Task Type="pushNotification" />
</BackgroundTasks>
</Extension>
backgroundTask.js
(function () {
//var backgroundTask = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current,
//taskName = backgroundTask.task.name;
Windows.Storage.ApplicationData.current.localSettings.values["hello"] = "world";
close();
})();
this is what my app.js does:
var taskName = "mySuperFancyBgTaskName";
var registerBackgroundTask = function() {
var btr = Windows.ApplicationModel.Background.BackgroundTaskRegistration;
var iter = btr.allTasks.first();
var taskRegistered = false;
while (iter.hasCurrent){
var ta = iter.current.value;
if (ta.name == taskName){
taskRegistered = true;
break;
}
iter.moveNext();
}
if (!taskRegistered){
var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
var trigger = new Windows.ApplicationModel.Background.PushNotificationTrigger();
builder.setTrigger( trigger );
builder.taskEntryPoint = "js\\lib\\backgroundTask.js";
builder.name = taskName;
try{
var task = builder.register();
//task.addEventListener("completed", onPushNotification);
}
catch (e){
console.error(e);
}
}
}
var channel;
var pushNotificationManager = Windows.Networking.PushNotifications.PushNotificationChannelManager;
var channelOperation = pushNotificationManager.createPushNotificationChannelForApplicationAsync();
channelOperation.then(function (newChannel) {
channel = newChannel;
saveChannelUriInSettings(channel.uri);
console.log("opened push notification channel with uri: " + channel.uri);
registerBackgroundTask();
},
function (error) {
console.log("Channel could not be retreived. " + error.number)
}
);
It seems that backgroundTask.js is never started,because there is nothing written in the localsettings. Tried to do some stuff there, but of course not able to debug there.
If I do
var onPushNotification = function (e) { ...}
channel.addEventListener("pushnotificationreceived", onPushNotification);
receiving raw push notifications works fine. So how do I get backgroundtask to work, so that it can save incoming push notifications? If it is working there is no need to define a event listener in the app to catch push notifications, right?
Any help is appreciated - thanks in advance!

Javascript code not displaying wanted output

I've written some code to display my favorites in IE8 but for an unknown reason I have no output on the screen despite the fact that my page is accepted by IE and that the test text 'this is a test' is displayed.
my code :
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso 8859-1" />
<script type="text/javascript">
var i = 0;
var favString = "";
var fso;
function GetFavourites(Folder) {
var FavFolder = fso.GetFolder(Folder);
//Gets Favourite Names & URL's for given folder.
var files = new Enumerator(FavFolder.Files);
for (; !files.atEnd(); files.moveNext()) {
var fil = files.item();
if (fil.Type == "Internet Shortcut") {
var textReader = fso.OpenTextFile(fil.Path, 1, false, -2);
var favtext = textReader.ReadAll();
var start = favtext.indexOf("URL", 16);
var stop = favtext.indexOf("\n", start);
favString += fil.Name.replace(/.url/, "");
favString += ":URL:";
//to separate favourite name & favorite URL
favString += favtext.substring(start + 4, stop - 1);
favorites.innerHTML += favString; // Not working !
favorites.innerHTML += 'test'; // Not working too !
favString += ":NEXT:"; //to separate favorites.
i++;
}
}
//Checks any subfolder exists
var subfolders = new Enumerator(FavFolder.SubFolders);
for (; !subfolders.atEnd(); subfolders.moveNext()) {
var folder = subfolders.item();
GetFavourites(folder.Path);
}
}
function Import() {
try {
fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso !== null) {
//Create windows script shell object to access Favorites folder in user system.
var object = new ActiveXObject("WScript.Shell");
var favfolderName = object.SpecialFolders("Favorites");
if (favString === "") {
GetFavourites(favfolderName);
}
}
}
catch (err) {
alert("Security settings to be modified in your browser ");
}
}
</script>
</head>
<body onload="Import()">
<p>this is a test</p> <!-- Working ! -->
<div id="favorites">
</div>
</body>
</html>
The following works for me:
var fso, favs = [];
function GetFavourites(Folder) {
var FavFolder = fso.GetFolder(Folder);
//Gets Favourite Names & URL's for given folder.
var files = new Enumerator(FavFolder.Files);
for (; !files.atEnd(); files.moveNext()) {
var fil = files.item();
if (fil.Type == "Internet Shortcut") {
var textReader = fso.OpenTextFile(fil.Path, 1, false, -2);
var favtext = textReader.ReadAll();
var start = favtext.indexOf("URL", 16);
var stop = favtext.indexOf("\n", start);
favString = fil.Name.replace(/.url/, "");
favString += ":URL:";
//to separate favourite name & favorite URL
favString += favtext.substring(start + 4, stop - 1);
favs.push(favString);
}
}
//Checks any subfolder exists
var subfolders = new Enumerator(FavFolder.SubFolders);
for (; !subfolders.atEnd(); subfolders.moveNext()) {
var folder = subfolders.item();
GetFavourites(folder.Path);
}
}
function Import() {
try {
fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso !== null) {
//Create windows script shell object to access Favorites folder in user system.
var object = new ActiveXObject("WScript.Shell");
var favfolderName = object.SpecialFolders("Favorites");
if (favString === "") {
GetFavourites(favfolderName);
}
}
}
catch (err) {
alert("Security settings to be modified in your browser ");
}
}
Note that all I changed was the output from an element to an array named favs. I also removed the i variable, because it wasn't used. After running the script, I checked the array in the developer tools console and it contained all my favourites.
If you're getting no output at all, then either fso is null in the Import method or files.AtEnd() always evaluates to false. Since you're focusing on IE here, you might consider placing alert methods in various places with values to debug (such as alert(fso);) throughout your expected code path.

Categories

Resources