Download files from filtered list

LabKey Support Forum (Inactive)
Download files from filtered list eva pujadas  2015-12-18 09:58
Status: Closed
 
We are using the URL field property in lists, to point to image files we have stored in the files directory of a LabKey folder's project using webdav.
E.g.: /labkey/_webdav/MyProject/MyFolder/%40files/${pictureFileName}

We would like to be able to download the image files, for example in a zip container, of the filtered rows in the list.
That would be a similar feature to the already existing "EXPORT" in lists, which can export the filtered rows'data in several formats: Excel, text file, etc...
The alternative we have at the moment is selecting the files in the "Files" web part and download them. The Download feature in the files web part performs exactly what we would need, i.e. zipping the selected files to download. The drawback of this option is that the files can not be selected based on data stored in lists.

From your experience, which would be the recommended approach to develop such a functionality?

Thanks a lot,
eva
 
 
xyang responded:  2015-12-18 10:44
Hi Eva,

Excel export will support embed images for 'Attachment' column type in the next release. You can define a list field to be of Attachment type (columns with URL field property won't support embed image for export) and attach the image file directly. Excel export will export the filtered list with the images embed along with the original image file name at the correct cell location. This is not quite the desired zip file format, but the images won't lose quality when embedded in excel.
 
Ben Bimber responded:  2015-12-18 10:54
Hi Eva,

I dont know your level or interest in writing javascript, but it appears that the action that the API file browser uses to download files could be co-opted by your list. You'd need to make a custom button for this. When clicked, it could take the checked rows, query the server to file the file paths or names (i assume this is a column in your list...), and then POST to /dav/zip.view with the directory and list of files to include. I dont believe this is a public API, so would theoretically be subject to change in future versions, though in this instance I think your risk is fairly low.

-Ben
 
eva pujadas responded:  2016-01-14 05:56
Hi Ben,

Thanks for your hint. That's exactly what we needed!
I have implemented a prototype. For the sake of sharing, I paste the relevant code:

<div id="queryWebPartTag"></div>

<script type="text/javascript">
    var listName = "some_list";
    var imageFolderPath = "some_folder";
    var imageColumnName = "some_column";
    var buttonLabel = "DOWNLOAD PICTURES";

    var queryWebPart = new LABKEY.QueryWebPart({
        renderTo : "queryWebPartTag",
        title : listName,
        schemaName : "lists",
        queryName : listName,
            buttonBar : {
            items : [
                    LABKEY.QueryWebPart.standardButtons.views,
                    LABKEY.QueryWebPart.standardButtons.insertNew,
                    LABKEY.QueryWebPart.standardButtons.deleteRows,
                    LABKEY.QueryWebPart.standardButtons.exportRows,
                    LABKEY.QueryWebPart.standardButtons.print,
                    LABKEY.QueryWebPart.standardButtons.pageSize,
                    {text : buttonLabel, handler : selectPictures}
            ]
        }
    });

    function selectPictures(dataRegion) {
        LABKEY.Query.selectRows({
            requiredVersion : 9.1,
            schemaName : dataRegion.getQueryConfig().schemaName,
            queryName : dataRegion.getQueryConfig().queryName,
            filterArray : dataRegion.getQueryConfig().filters,
            success : onSuccess,
            failure : onFailure
        });
    }

    function onSuccess(data) {
        var url = LABKEY.ActionURL.getBaseURL() + "_webdav" + LABKEY.ActionURL.getContainer() + "/@files/" + imageFolderPath + "?method=zip&depth=-1";
        for (var i = 0; i < data.rowCount; i++) {
            url = url + "&file=" + data.rows[i][imageColumnName].value;
        }
        window.location = url;
    }

    function onFailure(errorInfo, options, responseObj) {
        if (errorInfo && errorInfo.exception)
            alert("Failure: " + errorInfo.exception);
        else
            alert("Failure: " + responseObj.statusText);
    }
</script>