mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
16.35.2018 8536692bec03913455a683e062288ea7c96c2f04
Recovery (download) of backup files started.
4 files modified
63 ■■■■■ changed files
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java 21 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/FileListEntry.jsx 35 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/FileListPanel.jsx 1 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/FileListTable.jsx 6 ●●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
@@ -15,6 +15,7 @@
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
@Path("/archives")
@@ -66,4 +67,24 @@
        }
        return JsonUtils.toJson(items, prettyPrinter);
    }
    @GET
    @Path("/download")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    /**
     * @param archiveId
     * @param fileNumber The fileNumber of the file in the archive served by BorgButler's
     * {@link #getArchiveFileLIst(String, String, String, boolean, boolean)}
     */
    public Response downloadFilebyPath(@QueryParam("archiveId") String archiveId, @QueryParam("fileNumber") int fileNumber) {
        log.info("Downloading file #" + fileNumber + " of archive '" + archiveId + "'.");
        return null;
/*        byte[] byteArray = result.getAsByteArrayOutputStream().toByteArray();
        Response.ResponseBuilder builder = Response.ok(byteArray);
        builder.header("Content-Disposition", "attachment; filename=" + filename);
        // Needed to get the Content-Disposition by client:
        builder.header("Access-Control-Expose-Headers", "Content-Disposition");
        Response response = builder.build();
        return response;*/
    }
}
borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
@@ -1,14 +1,45 @@
import React from 'react';
import PropTypes from 'prop-types';
import Highlight from 'react-highlighter';
import {humanFileSize} from '../../../utilities/global';
import {IconDownload} from '../../general/IconComponents';
import {getResponseHeaderFilename, getRestServiceUrl, humanFileSize} from '../../../utilities/global';
import fileDownload from 'js-file-download';
function FileListEntry({entry, search}) {
function download(archiveId, fileNumber) {
    let filename;
    fetch(getRestServiceUrl('archives/download', {
        archiveId: archiveId,
        fileNumber: fileNumber
    }))
        .then(response => {
            if (!response.ok) {
                throw new Error(response.statusText);
            }
            filename = getResponseHeaderFilename(response.headers.get('Content-Disposition'));
            return response.blob();
        })
        .then(blob => {
            this.setState({
                running: false
            });
            fileDownload(blob, filename)
        })
        .catch(error => {
            console.log(error.toString());
        });
}
function FileListEntry({archiveId, entry, search}) {
    return (
        <tr>
            <td className={'tt'}>{entry.mode}</td>
            <td className={'tt'}>{entry.mtime}</td>
            <td className={'tt'}>{humanFileSize(entry.size, true, true)}</td>
            <td className={'tt'}>
                <div className={'btn'} onClick={() => download(archiveId, entry.fileNumber)}>
                    <IconDownload/></div>
            </td>
            <td className={'tt'}><Highlight search={search}>{entry.path}</Highlight></td>
        </tr>
    );
borgbutler-webapp/src/components/views/archives/FileListPanel.jsx
@@ -87,6 +87,7 @@
                        }}
                    />
                    <FileListTable
                        archiveId={this.props.archiveId}
                        entries={this.state.fileList}
                        search={this.state.filter.search}/>
                </React.Fragment>;
borgbutler-webapp/src/components/views/archives/FileListTable.jsx
@@ -3,7 +3,7 @@
import {Table} from 'reactstrap';
import FileListEntry from './FileListEntry';
function FileListTable({entries, search}) {
function FileListTable({archiveId, entries, search}) {
    const lowercaseSearch = search.split(' ')[0].toLowerCase();
    return (
        <Table striped bordered hover size={'sm'} responsive>
@@ -12,13 +12,14 @@
                <th>Mode</th>
                <th>Modified time</th>
                <th>Size</th>
                <th>Path</th>
                <th></th>
                <th>Path</th>
            </tr>
            </thead>
            <tbody>
            {entries
                .map((entry, index) => <FileListEntry
                    archiveId={archiveId}
                    entry={entry}
                    search={lowercaseSearch}
                    key={index}
@@ -29,6 +30,7 @@
}
FileListTable.propTypes = {
    archiveId: PropTypes.string,
    entries: PropTypes.array,
    search: PropTypes.string
};