diff --git a/runtime/BrowserWindow.cpp b/runtime/BrowserWindow.cpp
index e875b28..a73ab00 100644
--- a/runtime/BrowserWindow.cpp
+++ b/runtime/BrowserWindow.cpp
@@ -23,7 +23,6 @@
 #include <QInputDialog>
 #include <QLineEdit>
 #endif
-
 // App headers
 #include "BrowserWindow.h"
 #include "ConfigWindow.h"
@@ -42,6 +41,14 @@ BrowserWindow::BrowserWindow(QString url)
     m_widget = NULL;
     m_toolBtnBack = NULL;
     m_toolBtnForward = NULL;
+    m_downloadStarted = 0;
+    m_downloadCancelled = 0;
+    m_file = NULL;
+    m_downloadFilename = "";
+    m_defaultFilename = "";
+    m_progressDialog = NULL;
+    m_last_open_folder_path = QDir::currentPath();
+    m_dir = "";
 
     m_appServerUrl = url;
 
@@ -83,6 +90,11 @@ BrowserWindow::BrowserWindow(QString url)
     // Register the slot on tab index change
     connect(m_tabWidget,SIGNAL(currentChanged(int )),this,SLOT(tabIndexChanged(int )));
 
+    // Listen for the download file request from the web page
+    m_mainWebView->page()->setForwardUnsupportedContent(true);
+    connect(m_mainWebView->page(), SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(download(const QNetworkRequest &)));
+    connect(m_mainWebView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
+
     m_mainWebView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
 
     // Restore the geometry
@@ -199,6 +211,281 @@ int BrowserWindow::findURLTab(const QUrl &name)
     return 0;
 }
 
+// This slot will be called when user right click the download link and select "Save Link..."
+void BrowserWindow::download(const QNetworkRequest &request)
+{
+    // Check that request contains the data download at client side
+    QUrl name;
+    if (checkClientDownload(name, request))
+        return;
+
+    if (m_downloadStarted)
+    {
+        // Inform the user that a download is already started
+        QMessageBox::information(this, tr("Download warning"), tr("File download already in progress: %1").arg(m_defaultFilename));
+        return;
+    }
+
+    m_defaultFilename = QFileInfo(request.url().toString()).fileName();
+
+    QFileDialog save_dialog(this);
+    save_dialog.setAcceptMode(QFileDialog::AcceptSave);
+    save_dialog.setWindowTitle(tr("Save file"));
+    save_dialog.setDirectory(m_last_open_folder_path);
+    save_dialog.selectFile(m_defaultFilename);
+
+    QObject::connect(&save_dialog, SIGNAL(directoryEntered(const QString &)), this, SLOT(current_dir_path(const QString &)));
+    m_dir = m_last_open_folder_path;
+    QString fileName = "";
+    QString f_name = "";
+
+    if (save_dialog.exec() == QDialog::Accepted) {
+        fileName = save_dialog.selectedFiles().first();
+        f_name = fileName.replace(m_dir, "");
+        // remove the first character from fiename
+        f_name.remove(0,1);
+        m_defaultFilename = f_name;
+    }
+    else
+        return;
+
+    fileName = m_dir + fileName;
+    // clear the last folder open path
+    m_dir.clear();
+
+#ifdef __APPLE__
+    // Check that user has given valid file name or not - forward slash not allowed in file name
+    // In Mac OSX, forward slash is converted to colon(:) by Qt so we need to check for colon.
+    if (f_name.indexOf(":") != -1)
+    {
+        QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
+        return;
+    }
+#else
+    // Check that user has given valid file name or not - forward slash not allowed in file name
+    if (f_name.indexOf("/") != -1)
+    {
+        QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
+        return;
+    }
+#endif
+
+    if (fileName.isEmpty())
+        return;
+    else
+    {
+        m_downloadFilename = fileName;
+
+        QNetworkRequest newRequest = request;
+        newRequest.setAttribute(QNetworkRequest::User, fileName);
+
+        QObject *obj_web_page = QObject::sender();
+        if (obj_web_page != NULL)
+        {
+            QWebPage *sender_web_page = dynamic_cast<QWebPage*>(obj_web_page);
+            if (sender_web_page != NULL)
+            {
+                QNetworkAccessManager *networkManager = sender_web_page->networkAccessManager();
+                QNetworkReply *reply = networkManager->get(newRequest);
+                if (reply != NULL)
+                {
+                    m_downloadStarted = 1;
+                    m_downloadCancelled = 0;
+                    // Connect the signal for downloadProgress and downloadFinished for file download
+                    connect( reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadFileProgress(qint64, qint64)) );
+                    connect( reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
+                }
+            }
+        }
+    }
+}
+
+//This slot will called in chunk and give the progress for the file download
+void BrowserWindow::downloadFileProgress(qint64 readData, qint64 totalData)
+{
+    QNetworkReply *reply = ((QNetworkReply*)sender());
+    QNetworkRequest request = reply->request();
+    QVariant v = request.attribute(QNetworkRequest::User);
+
+    // Is download is canceled by the user then no action is taken, just return
+    if (m_downloadCancelled)
+        return;
+
+    if(reply != NULL && reply->error() != QNetworkReply::NoError)
+    {
+        qDebug() << "Network error occurred whilst downloading: " << m_defaultFilename;
+        return;
+    }
+
+    // Download is not yet started so open the file first time.
+    if (!m_file)
+    {
+        m_file = new QFile(m_downloadFilename);
+        if (!m_file->open(QIODevice::WriteOnly))
+        {
+            qDebug() << "Error opening file: " << m_downloadFilename;
+            m_downloadFilename.clear();
+            m_defaultFilename.clear();
+            m_downloadStarted = 0;
+            return;
+        }
+
+        // Start downloading progress bar
+        m_progressDialog = new QProgressDialog (tr("Downloading file: %1 ").arg(m_defaultFilename), "Cancel", readData, totalData, this);
+        m_progressDialog->setWindowModality(Qt::WindowModal);
+        m_progressDialog->setWindowTitle("Download progress");
+        m_progressDialog->setMinimumWidth(450);
+        m_progressDialog->setMinimumHeight(80);
+        m_progressDialog->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
+        QObject::connect(m_progressDialog, SIGNAL(canceled()), this, SLOT(progressCanceled()));
+        m_progressDialog->show();
+    }
+
+    if (m_file)
+    {
+        // Write the data to file
+        m_file->write(reply->read(readData));
+        m_progressDialog->setValue(readData);
+
+        // As read data and totalData difference is zero means downloading is finished
+        if ((totalData - readData) == 0)
+        {
+            if (m_progressDialog)
+            {
+                delete m_progressDialog;
+                m_progressDialog = NULL;
+            }
+
+            // Downloading complted so we need to display the message
+            // Inform user that downloading is completed
+            QMessageBox::information(this, tr("Download completed"), tr("Successfully downloaded %1").arg(m_defaultFilename));
+            m_downloadFilename.clear();
+            m_defaultFilename.clear();
+            m_downloadStarted = 0;
+            m_downloadCancelled = 0;
+            if (m_file)
+            {
+                delete m_file;
+                m_file = NULL;
+            }
+        }
+    }
+}
+
+//This slot will called when user cancel the downloading file which is in progress.
+void BrowserWindow::progressCanceled()
+{
+    m_downloadCancelled = 1;
+
+    if (m_progressDialog)
+    {
+        delete m_progressDialog;
+        m_progressDialog = NULL;
+    }
+
+    if (m_file)
+    {
+        delete m_file;
+        m_file = NULL;
+    }
+
+    m_downloadFilename.clear();
+    m_defaultFilename.clear();
+    m_downloadStarted = 0;
+}
+
+// This slot will called when file downloading is finished
+void BrowserWindow::downloadFinished()
+{
+    if (m_progressDialog)
+    {
+        delete m_progressDialog;
+        m_progressDialog = NULL;
+    }
+
+    // Inform user that downloading is completed
+    if (m_downloadStarted)
+        QMessageBox::information(this, tr("Download completed"), tr("Successfully downloaded %1").arg(m_defaultFilename));
+
+    m_downloadFilename.clear();
+    m_defaultFilename.clear();
+    m_downloadStarted = 0;
+    m_downloadCancelled = 0;
+    if (m_file)
+    {
+        delete m_file;
+        m_file = NULL;
+    }
+}
+
+// This slot will be called when user directly click on any download file
+void BrowserWindow::unsupportedContent(QNetworkReply * reply)
+{
+    if (m_downloadStarted)
+    {
+        //Inform the user that one download already started
+        QMessageBox::information(this, tr("Download warning"), tr("File download already in progress: %1").arg(m_defaultFilename));
+        return;
+    }
+
+    m_defaultFilename = QFileInfo(reply->url().toString()).fileName();
+    QFileDialog save_dialog(this);
+    save_dialog.setAcceptMode(QFileDialog::AcceptSave);
+    save_dialog.setWindowTitle(tr("Save file"));
+    save_dialog.setDirectory(m_last_open_folder_path);
+    save_dialog.selectFile(m_defaultFilename);
+
+    QObject::connect(&save_dialog, SIGNAL(directoryEntered(const QString &)), this, SLOT(current_dir_path(const QString &)));
+    m_dir = m_last_open_folder_path;
+    QString fileName = "";
+    QString f_name = "";
+
+    if (save_dialog.exec() == QDialog::Accepted) {
+        fileName = save_dialog.selectedFiles().first();
+        f_name = fileName.replace(m_dir, "");
+        // remove the first character from fiename
+        f_name.remove(0,1);
+        m_defaultFilename = f_name;
+    }
+    else
+        return;
+
+    fileName = m_dir + fileName;
+    // clear the last folder open path
+    m_dir.clear();
+
+#ifdef __APPLE__
+    // Check that user has given valid file name or not - forward slash not allowed in file name
+    // In Mac OSX, forward slash is converted to colon(:) by Qt so we need to check for colon.
+    if (f_name.indexOf(":") != -1)
+    {
+        QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
+        return;
+    }
+#else
+    // Check that user has given valid file name or not - forward slash not allowed in file name
+    if (f_name.indexOf("/") != -1)
+    {
+        QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
+        return;
+    }
+#endif
+
+    if (fileName.isEmpty())
+        return;
+    else
+    {
+        m_downloadFilename = fileName;
+        if (reply != NULL)
+        {
+            m_downloadStarted = 1;
+            m_downloadCancelled = 0;
+            connect( reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadFileProgress(qint64, qint64)));
+            connect( reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
+        }
+    }
+}
+
 // Slot: When the tab index change, hide/show the toolbutton displayed on tab
 void BrowserWindow::tabIndexChanged(int index)
 {
@@ -340,9 +627,142 @@ void BrowserWindow::tabTitleChanged(const QString &str)
     }
 }
 
+// This function will used to download the data set in encoded URL so data will be downloaded at client side.
+bool BrowserWindow::checkClientDownload(const QUrl &name, const QNetworkRequest &request)
+{
+    QString mime_type = "";
+    QString file_name = "";
+    QString write_data = "";
+    QString csv_data = "";
+    bool return_val = false;
+
+    /*
+    In Qt version 5.5, "download" signal is emitted when 'download' attribute is set on 'a' tag.
+    In "download" signal emission, name will be empty and data will be in request object.
+    Earlier version ( < 5.5 ), "urlLinkClicked" signal is emitted so name will contain the object data.
+    */
+    if (name.isEmpty())
+        csv_data = QFileInfo(request.url().toString()).fileName();
+    else
+        csv_data = QString::fromUtf8(name.toEncoded());
+
+    QUrlQuery downloadData(csv_data);
+    QStringList keyValueData = csv_data.split("&");
+    file_name = downloadData.queryItemValue("filename");
+    write_data = downloadData.queryItemValue("value");
+
+    int key_value_length = keyValueData.size();
+    int i_count = 0;
+
+    // we have key value data so we need to tokeniza it and find the values
+    while (i_count < key_value_length)
+    {
+        //Extract the extension after "data:" word found from encoded url.
+        QString start_match_string = "data:";
+        int s_offset = keyValueData.at(i_count).indexOf(start_match_string);
+        if (s_offset != -1)
+        {
+            int format_offset = keyValueData.at(i_count).indexOf("/");
+            mime_type = keyValueData.at(i_count).mid((format_offset+1));
+            break;
+        }
+
+        int split_offset = keyValueData.at(i_count).indexOf("=");
+        if (split_offset == -1)
+        {
+            mime_type = keyValueData.at(i_count);
+            break;
+        }
+
+        i_count += 1;
+    }
+
+    // write data to file
+    if (!write_data.isEmpty())
+    {
+        QString filename = "";
+        QString f_name = "";
+        QFileDialog saveAsdialog(this);
+        saveAsdialog.setAcceptMode(QFileDialog::AcceptSave);
+        saveAsdialog.selectNameFilter(tr("Files (*.%1)").arg(mime_type));
+        saveAsdialog.setWindowTitle(tr("Save %1 file").arg(mime_type));
+        saveAsdialog.setDirectory(m_last_open_folder_path);
+        saveAsdialog.selectFile(file_name);
+        saveAsdialog.setDefaultSuffix(mime_type);
+
+        QObject::connect(&saveAsdialog, SIGNAL(directoryEntered(const QString &)), this, SLOT(current_dir_path(const QString &)));
+        m_dir = m_last_open_folder_path;
+
+        if (saveAsdialog.exec() == QDialog::Accepted) {
+            filename = saveAsdialog.selectedFiles().at(0);
+            QString filename = saveAsdialog.selectedFiles().first();
+            f_name = filename.replace(m_dir, "");
+            // remove the first character from fiename
+            f_name.remove(0,1);
+        }
+
+        // clear the last folder open path
+        m_dir.clear();
+
+        return_val = true;
+
+#ifdef __APPLE__
+        // Check that user has given valid file name or not - forward slash not allowed in file name
+        // In Mac OSX, forward slash is converted to colon(:) by Qt so we need to check for colon.
+        if (f_name.indexOf(":") != -1)
+        {
+            QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
+            return return_val;
+        }
+#else
+        // Check that user has given valid file name or not - forward slash not allowed in file name
+        if (f_name.indexOf("/") != -1)
+        {
+            QMessageBox::information(this, tr("File name error"), tr("Invalid file name"));
+            return return_val;
+        }
+#endif
+        if(!filename.isEmpty())
+        {
+            // save the last open folder path
+            m_last_open_folder_path = QFileInfo(filename).path();
+            // Decode the encoded uri data
+            QString csvData = QUrl::fromPercentEncoding(write_data.toUtf8());
+
+            QFile csvfile(filename);
+            if (!csvfile.open(QIODevice::WriteOnly | QIODevice::Text))
+            {
+                QMessageBox::information(this, tr("Save csv file"), tr("Error while opening file %1").arg(filename));
+                return return_val;
+            }
+            // Write the csv data to file
+            qint64 data_return = csvfile.write(csvData.toUtf8().constData());
+            if (data_return == -1)
+            {
+                QMessageBox::information(this, tr("Save csv file"), tr("Error while writing data to file %1").arg(filename));
+                csvfile.close();
+                return return_val;
+            }
+            csvfile.close();
+        }
+    }
+
+    return return_val;
+}
+
+void BrowserWindow::current_dir_path(const QString &dir)
+{
+    m_dir = dir;
+}
+
 // Slot: Link is open from pgAdmin mainwindow
 void BrowserWindow::urlLinkClicked(const QUrl &name)
 {
+    // Check that request contains the data download at client side
+    QNetworkRequest request;
+    if (checkClientDownload(name, request))
+        return;
+
     // First check is there any tab opened with same URL then open it again.
     int tabFound = findURLTab(name);
 
@@ -353,6 +773,11 @@ void BrowserWindow::urlLinkClicked(const QUrl &name)
         m_addNewGridLayout->setContentsMargins(0, 0, 0, 0);
         m_addNewWebView = new WebViewWindow(m_addNewTab);
 
+	// Listen for the download request from the web page
+	m_addNewWebView->page()->setForwardUnsupportedContent(true);
+        connect(m_addNewWebView->page(), SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(download(const QNetworkRequest &)));
+        connect(m_addNewWebView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(unsupportedContent(QNetworkReply*)));
+
         m_widget = new QWidget(m_addNewTab);
         m_toolBtnBack = new QToolButton(m_widget);
         m_toolBtnBack->setFixedHeight(PGA_BTN_SIZE);
diff --git a/runtime/BrowserWindow.h b/runtime/BrowserWindow.h
index 43f90fe..7635549 100644
--- a/runtime/BrowserWindow.h
+++ b/runtime/BrowserWindow.h
@@ -54,6 +54,12 @@ public slots:
     void tabIndexChanged(int index);
     void goBackPage();
     void goForwardPage();
+    void download(const QNetworkRequest &request);
+    void unsupportedContent(QNetworkReply * reply);
+    void downloadFinished();
+    void downloadFileProgress(qint64 , qint64 );
+    void progressCanceled();
+    void current_dir_path(const QString &dir);
 
 private:
     QString m_appServerUrl;
@@ -79,10 +85,19 @@ private:
 
     bool m_initialLoad;
     int m_loadAttempt;
+    QString m_downloadFilename;
+    int m_downloadStarted;
+    int m_downloadCancelled;
+    QFile *m_file;
+    QProgressDialog *m_progressDialog;
+    QString m_defaultFilename;
+    QString m_last_open_folder_path;
+    QString m_dir;
 
     void createActions();
     void pause(int seconds = 1);
     int  findURLTab(const QUrl &name);
+    bool checkClientDownload(const QUrl &name, const QNetworkRequest &request);
 };
 
 #endif // BROWSERWINDOW_H
diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
index 295caf4..2df2b5f 100644
--- a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
@@ -2587,7 +2587,7 @@ define(
                 keys = _.pluck(self.columns, 'name');
 
             // Fetch the items from fullCollection and convert it as csv format
-            var csv = labels.join(',') + '\n';
+            var csv = keys.join(',') + '\n';
             csv += coll.map(function(item) {
                 return _.map(keys, function(key) {
                   var cell = csv_col [key].cell,
@@ -2600,7 +2600,7 @@ define(
             }).join('\n');
 
             // Download the file.
-            var encodedUri = encodeURI('data:text/csv;charset=utf-8,' + csv),
+            var encodedUri = encodeURI('data:text/csv&charset=utf-8&filename=download.csv&value=' + csv),
                     link = document.createElement('a');
             link.setAttribute('href', encodedUri);
 
