Scriptを使用してファイルをダウンロードする方法について

Fagi
Tera Contributor

いつもお世話になっております。
GlideReocrdをデータベースビューの一覧画面で、ボタンを押すとCSVファイルがダウンロードされるようなUIアクションを作成したいと考えております。
UI Actionのボタンが押されると、Script Includeが呼び出され、Script IncludeのScriptフィールドのコードに従って、ファイルをダウンロードすることができような使用にしたいと考えております。
以下の画像のコードを参考にしようと思ったのですが、この画像のコードでは最後にレコードにファイルを添付しています。
上記でも記載した通り、ファイルを添付せず、ダウンロードしたいです。
できれば、このコードをそのまま使って、添付されている部分を直接ダウンロードするコードに置き換えたいのですが、可能でしょうか?
前提として、Export Importモジュールの設定で、csvヘッダーのヘッダの出力をカラムネームにしたまま、カラムラベルでCSVファイルのヘッダーを出力したいのでスクリプトでヘッダを直接指定します。
何かご教授いただければ幸いです。
よろしくお願いいたします。

スクリーンショット 2022-10-04 184301.png

1 ACCEPTED SOLUTION

リストビューのUIActionで動くClientScript版を作ってみました。この方式の場合、一度Clientsideにデータ読み込んで、再度ダウンロードすることになるので、2回通信しています。このあとCSVの変換処理を含めると処理やデーター量によっては遅くなります。

function onTestClientCSV() {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open('GET', '/incident_list.do?sysparm_query=&CSV', true);
    xmlhttp.setRequestHeader("X-UserToken", g_ck);
    xmlhttp.setRequestHeader("Accept", "application/json");
    xmlhttp.setRequestHeader("Content-Type", "application/json");
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
            var blob = new Blob([bom, xmlhttp.responseText], {
                type: 'text/csv'
            });
            var document = g_list.getContainer().ownerDocument;
            var window = g_list.getContainer().ownerDocument.defaultView;
            var url = (window.URL || window.webkitURL).createObjectURL(blob);
            var link = document.createElement('a');
            link.download = 'incident.csv';
            link.href = url;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
    xmlhttp.send();
}

 

View solution in original post

4 REPLIES 4

iwai
Giga Sage

ClientScript側でCSVを作成してDownloadする方法も考えてみましたが、容量や速度的にやめておいた方が良いなと思いました。

そこで、添付ファイルを自動的に消す 一時利用のScheduleJob を作成して、そのレコードに添付する方法を作ってみました。 添付ファイルはScheduleJobにあり、ScheduleJobは添付ファイを消した後、ScheduleJobも消えます。制限時間内に添付ファイルの URLからダウンロードすると良いです。

function deleteAttachment(attachmentSysID) {
    var gsa = new GlideSysAttachment();
    gsa.deleteAttachment(attachmentSysID);
}

var sched = new ScheduleOnce();
sched.script = 'true';
sched.setAsSeconds(24*60*60); //24時間後に実行
//sched.setAsSeconds(60); //60秒後に実行
sched.setLabel('Test Attachment');
var sysid = sched.schedule();
var grSchedule = new GlideRecord('sys_trigger');
grSchedule.get(sysid);
var gsa = new GlideSysAttachment();
// 仮のCSVファイル
var csvData = 'A,B,C\n1,2,3';
attSysid = gsa.write(grSchedule, 'Test_CsvFile.csv', 'application/csv', csvData);

// 添付ファイルを消す処理を登録
grSchedule.script = '(' + deleteAttachment.toString() + ')("' + attSysid + '");'
grSchedule.update();

 

Fagi
Tera Contributor

iwaiさん

いつもお世話になっております。

回答ありがとうございます。

ファイルをダウンロードする方法は容量がおもいとのことですが、ダウンロードする方法でも実装は可能ということで認識あってますでしょうか?

容量や速度が気になるとのことですが、何が原因で重くなるのでしょうか?

もし実装が可能であれば、コードの例などを投稿してただけると幸いです。

お手数をおかけしますが、宜しくお願い致します。

クライアント側でCSVを扱う場合、サーバーからCSVの原本となるデータをクライアント側に出力して、クライアント側でCSVファイルに加工して、さらにダウンロードするため出力します。2回の全量データの通信が発生することと、CSV化するデータが数十メガになるほど膨大であると、通信負荷や時間も大きくなり、それをクライアント側で膨大に処理する必要が出てきます。このような遅延はユーザー側からみて処理が停止したように見えて中断する可能性もあります。

そうするくらいなら、サーバー側でCSV ファイルまで作成して、URLだけクライアント側に渡すほうが、処理は早く、負荷も少なく、デメリットがありません。

サーバー側でファイルを作りたくない理由や要件などありましたら、別の検討ができるかもしれません。

少なくとも、私の提示したScriptではUIActionに組み込むことができますし、サーバー側にファイルを作成しても、一時的なもので自動的に消すことができます。誰かに見られたり、変更されたりもしません。複数同時のダウンロードにも問題なく処理できます。

リストビューのUIActionで動くClientScript版を作ってみました。この方式の場合、一度Clientsideにデータ読み込んで、再度ダウンロードすることになるので、2回通信しています。このあとCSVの変換処理を含めると処理やデーター量によっては遅くなります。

function onTestClientCSV() {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open('GET', '/incident_list.do?sysparm_query=&CSV', true);
    xmlhttp.setRequestHeader("X-UserToken", g_ck);
    xmlhttp.setRequestHeader("Accept", "application/json");
    xmlhttp.setRequestHeader("Content-Type", "application/json");
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
            var blob = new Blob([bom, xmlhttp.responseText], {
                type: 'text/csv'
            });
            var document = g_list.getContainer().ownerDocument;
            var window = g_list.getContainer().ownerDocument.defaultView;
            var url = (window.URL || window.webkitURL).createObjectURL(blob);
            var link = document.createElement('a');
            link.download = 'incident.csv';
            link.href = url;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
    xmlhttp.send();
}