Question
· Jul 11, 2016

ZEN Mojo : file download code sample

Hello,

One of our AP would like us to provide the file upload/download sample code by using ZEN Mojo.

I already provided them the attached "upload-sample".

I tried to create the "download-sample" in a similar way, but I couldn't do it yet.

Does anyone have a good idea/sample about this?

I'd like to download the server side file(e.g. c:\temp\nene.jpg) into client machine with a OpenFileDialog(image.png).

 

Thank you in advance.

Discussion (6)0
Log in or sign up to continue

I use the following code:

Class Form.File Extends %Persistent
{

/// Full filepath (path+name)
Property name As %String(MAXLEN = 1000, MINLEN = 1) [ Required ];

/// Description
Property description As %String(MAXLEN = 500);

/// Attachmentt SHA Hash in Base64
Property attachmentHASH As %String;

/// The file itself (data is stored on disk, it's just a link)
Property stream As %FileBinaryStream;

/// Save file
Method %OnNew(name As %String = "", description As %String = "", stream As %Stream.Object = {##class(%FileBinaryStream).%New()}) As %Status [ Private, ServerOnly = 1 ]
{
    #dim sc As %Status = $$$OK
    set ..name = ##class(%File).GetFilename(name)
    set ..description = description
    set ..stream.Filename = name
    set ..attachmentHASH = $system.Encryption.Base64Encode($zcvt($system.Encryption.SHAHashStream(512, ..stream, .sc),"O","UTF8"), 1)  
    return:$$$ISERR(sc) sc
    set sc = ..stream.CopyFromAndSave(stream)
    quit sc
}

/// Serve file in web context
Method serve() As %Status
{
    #dim sc As %Status = $$$OK
    #dim %response As %CSP.Response
    kill %request.Data
    set %request.Data("STREAMOID",1)= ##class(%CSP.StreamServer).Encrypt(..stream.%Oid())
    if ##class(%CSP.StreamServer).OnPreHTTP() {
        set %response.Headers("Content-Disposition")="attachment; filename*=UTF-8''"_##class(%CSP.Page).EscapeURL(..name,"UTF8")
        set st = ##class(%CSP.StreamServer).OnPage()
    }

    quit sc
}

During file upload new Form.File class object gets created and saved, and for download the requested object and calls the serve method.

Note, that this code is not specific to ZEN Mojo, but rather a generic CSP version.

My samples is using 2 JavaScript libraries.
 1)  JSZip(http://stuk.github.io/jszip)
 2) FileSaver.js(https://github.com/eligrey/FileSaver.js/).
These library can downloads some files from one path at once and save as one Zip file.
Simple samples is below:
 

<!DOCTYPE html>downloadandzip-mojo-dojo_0.zip
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
 <script type="text/javascript" src="http://stuk.github.io/jszip/dist/jszip.min.jscharset="utf-8"></script>
 <script src="FileSaver.min.js" charset="utf-8"></script>

</head>
<body>
<form name=f1 method=post>
<h2>Download+Zip Simple sample</h2>
Please set urlList variable correct file path in startDL() before testing.
<br>
<input type="button" name="b1" value="Download" onclick=startDL()>
</form>
<script type='text/javascript'>
function startDL(){
// urlListにはダウンロード用ファイルを直接指定しています。
// 【注意】日本語を含むファイル名はダウンロードできません。
var urlList ["./ImageTest/IMG_3587.JPG","./ImageTest/IMG_3598.JPG"]
console.log(urlList);

zip new JSZip();
deferreds $.Deferred();
var promise deferreds;

$.map(urlList,function(value,index) {
    console.log('urlList:index='+index+' = '+value);
    console.log('match() : '+value.match(".+/(.+?)([\?#;].*)?$")[1]);

promise promise.then( function() {
var newPromise new $.Deferred();

var xhrnew XMLHttpRequest();
  xhr.open('GET',value,true);
xhr.responseType='arraybuffer';
xhr.addEventListener('load', function() {

// zipにレスポンスデータ追加
zip.file(value.match(".+/(.+?)([\?#;].*)?$")[1],xhr.response);
newPromise.resolve();
});
xhr.send();
        return newPromise;
});

});

promise.then( function() {
zip.generateAsync({type:"blob"}).then( function(content){
saveAs(content,'test.zip');
});

});
deferreds.resolve();
}
</script>
</body>
</html>

I attached sample for mojo+dojo.

My samples is using 2 JavaScript libraries.
 1)  JSZip(http://stuk.github.io/jszip)
 2)  FileSaver.js(https://github.com/eligrey/FileSaver.js/).
These library can downloads some files from one path at once and save as one Zip file.
Simple samples is below:::
 

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
 <script type="text/javascript" src="http://stuk.github.io/jszip/dist/jszip.min.js" charset="utf-8"></script>
 <script src="FileSaver.min.js" charset="utf-8"></script>
</head>
<body>
<form name=f1 method=post>
<h2>Download+Zip Simple sample</h2>
Please set urlList variable correct file path in startDL() before testing.
<br>
<input type="button" name="b1" value="Download" onclick=startDL()>
</form>
<script type='text/javascript'>
function startDL(){

// urlListにはダウンロード用ファイルを直接指定しています。
// 【注意】日本語を含むファイル名はダウンロードできません。
var urlList = ["./ImageTest/IMG_3587.JPG","./ImageTest/IMG_3598.JPG"]
console.log(urlList);

zip = new JSZip();
deferreds = $.Deferred();
var promise = deferreds;


$.map(urlList,function(value,index) {
    console.log('urlList:index='+index+' = '+value);
    console.log('match() : '+value.match(".+/(.+?)([\?#;].*)?$")[1]);

promise = promise.then( function() {
var newPromise = new $.Deferred();

var xhr= new XMLHttpRequest();
  xhr.open('GET',value,true);
xhr.responseType='arraybuffer';
xhr.addEventListener('load', function() {

// zipにレスポンスデータ追加
zip.file(value.match(".+/(.+?)([\?#;].*)?$")[1],xhr.response);
newPromise.resolve();
});
xhr.send();
        return newPromise;
});

});

promise.then( function() {
zip.generateAsync({type:"blob"}).then( function(content){
saveAs(content,'test.zip');
});

});
deferreds.resolve();
}
</script>
</body>
</html>

I attached sample for mojo+dojo.downloadandzip-mojo-dojo_1.zip