diff --git a/client/src/app/instance/search/components/result/datatable-actions.component.html b/client/src/app/instance/search/components/result/datatable-actions.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a1ff010a95fbcfa5304aadb79791f8841c341466
--- /dev/null
+++ b/client/src/app/instance/search/components/result/datatable-actions.component.html
@@ -0,0 +1,32 @@
+<div *ngIf="getDataset().config.datatable.datatable_selectable_rows" class="btn-group mb-2" dropdown [isDisabled]="selectedData.length < 1">
+    <button id="button-basic" dropdownToggle type="button" class="btn btn-primary dropdown-toggle" aria-controls="dropdown-basic">
+        Actions <span class="caret"></span>
+    </button>
+    <ul id="dropdown-basic" *dropdownMenu class="dropdown-menu" role="menu" aria-labelledby="button-basic">
+        <li *ngIf="getConfigDownloadResultFormat('download_csv')" role="menuitem">
+            <a class="dropdown-item" [href]="getUrl('csv')" (click)="click($event, getUrl('csv'), 'csv')">
+                <span class="fas fa-file-csv"></span> Download CSV
+            </a>
+        </li>
+        <li *ngIf="getConfigDownloadResultFormat('download_ascii')" role="menuitem">
+            <a class="dropdown-item" [href]="getUrl('ascii')" (click)="click($event, getUrl('ascii'), 'txt')">
+                <span class="fas fa-file"></span> Download ASCII
+            </a>
+        </li>
+        <li *ngIf="getConfigDownloadResultFormat('download_vo')" role="menuitem">
+            <a class="dropdown-item" [href]="getUrl('votable')" (click)="click($event, getUrl('votable'), 'xml')">
+                <span class="fas fa-file"></span> VOtable
+            </a>
+        </li>
+        <li *ngIf="getConfigDownloadResultFormat('download_vo')" role="menuitem">
+            <a class="dropdown-item" (click)="broadcastVotable()">
+                <span class="fas fa-broadcast-tower"></span> Broadcast VOtable
+            </a>
+        </li>
+        <li *ngIf="getConfigDownloadResultFormat('download_archive')" role="menuitem">
+            <a class="dropdown-item" [href]="getUrlArchive()" (click)="click($event, getUrlArchive(), 'zip')">
+                <span class="fas fa-archive"></span> Download files archive
+            </a>
+        </li>
+    </ul>
+</div>
diff --git a/client/src/app/instance/search/components/result/datatable-actions.component.ts b/client/src/app/instance/search/components/result/datatable-actions.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5c29499606f57e2117b0fbec16fc780b7a23d630
--- /dev/null
+++ b/client/src/app/instance/search/components/result/datatable-actions.component.ts
@@ -0,0 +1,117 @@
+import { Component, Input, Output, EventEmitter } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { ToastrService } from 'ngx-toastr';
+
+import { Dataset, Attribute } from 'src/app/metamodel/models';
+import { Criterion, ConeSearch, criterionToString } from 'src/app/instance/store/models';
+import { getHost } from 'src/app/shared/utils';
+import { AppConfigService } from 'src/app/app-config.service';
+
+@Component({
+    selector: 'app-datatable-actions',
+    templateUrl: 'datatable-actions.component.html'
+})
+export class DatatableActionsComponent {
+    @Input() selectedData: any[] = [];
+    @Input() datasetSelected: string;
+    @Input() datasetList: Dataset[];
+    @Input() attributeList: Attribute[];
+    @Input() criteriaList: Criterion[];
+    @Input() outputList: number[];
+    @Input() coneSearch: ConeSearch;
+    @Input() dataLength: number;
+    @Input() sampRegistered: boolean;
+    @Output() broadcast: EventEmitter<string> = new EventEmitter();
+
+    constructor(private appConfig: AppConfigService, private http: HttpClient, private toastr: ToastrService) { }
+
+    /**
+     * Checks if the download format is allowed by Anis Admin configuration.
+     *
+     * @param  {string} format - The file format to download.
+     *
+     * @return boolean
+     */
+    getConfigDownloadResultFormat(format: string): boolean {
+        const dataset = this.getDataset();
+        return dataset.config.download[format];
+    }
+
+    getDataset() {
+        return this.datasetList.find(d => d.name === this.datasetSelected);
+    }
+
+    /**
+     * Returns URL to download file for the given format.
+     *
+     * @param  {string} format - The file format to download.
+     *
+     * @return string
+     */
+    getUrl(format: string): string {
+        let query: string = `${getHost(this.appConfig.apiUrl)}/search/${this.datasetSelected}?a=${this.outputList.join(';')}`;
+        if (this.criteriaList.length > 0) {
+            query += `&c=${this.criteriaList.map(criterion => criterionToString(criterion)).join(';')};${this.getCriterionSelectedData()}`;
+        } else {
+            query += `&c=${this.getCriterionSelectedData()}`;
+        }
+        if (this.coneSearch) {
+            query += `&cs=${this.coneSearch.ra}:${this.coneSearch.dec}:${this.coneSearch.radius}`;
+        }
+        query += `&f=${format}`;
+        return query;
+    }
+
+    getCriterionSelectedData() {
+        const attributeId = this.attributeList.find(a => a.search_flag === 'ID');
+        return `${attributeId.id}::in::${this.selectedData.join('|')}`;
+    }
+
+    /**
+     * Returns URL to download archive.
+     *
+     * @return boolean
+     */
+    getUrlArchive(): string {
+        let query: string = `${getHost(this.appConfig.apiUrl)}/archive/${this.datasetSelected}?a=${this.outputList.join(';')}`;
+        if (this.criteriaList.length > 0) {
+            query += `&c=${this.criteriaList.map(criterion => criterionToString(criterion)).join(';')};${this.getCriterionSelectedData()}`;
+        } else {
+            query += `&c=${this.getCriterionSelectedData()}`;
+        }
+        if (this.coneSearch) {
+            query += `&cs=${this.coneSearch.ra}:${this.coneSearch.dec}:${this.coneSearch.radius}`;
+        }
+        return query;
+    }
+
+    /**
+     * Emits event to  action to broadcast data.
+     *
+     * @fires EventEmitter<string>
+     */
+    broadcastVotable(): void {
+        this.broadcast.emit(this.getUrl('votable'));
+    }
+
+    /**
+     * Allows to download file.
+     */
+    click(event, href, extension): void {
+        event.preventDefault();
+
+        if (extension === 'zip') {
+            this.toastr.info('Achive is under construction, please wait', 'Download archive');
+        }
+
+        this.http.get(href, {responseType: "blob"}).subscribe(
+            data => {
+                let downloadLink = document.createElement('a');
+                downloadLink.href = window.URL.createObjectURL(data);
+                downloadLink.setAttribute('download', `${this.datasetSelected}.${extension}`);
+                downloadLink.click();
+            }
+        );
+    }
+}
diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.html b/client/src/app/instance/search/components/result/datatable-tab.component.html
index f9f6b3aaa6a57531613c217cf6a1ebf3501bc5be..b0ad6b0c98a437955dc1be5f759df0ce1f640a94 100644
--- a/client/src/app/instance/search/components/result/datatable-tab.component.html
+++ b/client/src/app/instance/search/components/result/datatable-tab.component.html
@@ -8,6 +8,18 @@
                 <span *ngIf="!ag.isOpen"><span class="fas fa-chevron-down"></span></span>
             </span>
         </button>
+        <app-datatable-actions 
+            [selectedData]="selectedData"
+            [datasetSelected]="datasetSelected"
+            [datasetList]="datasetList"
+            [attributeList]="attributeList"
+            [criteriaList]="criteriaList"
+            [outputList]="outputList"
+            [coneSearch]="coneSearch"
+            [dataLength]="dataLength"
+            [sampRegistered]="sampRegistered"
+            (broadcast)="broadcast.emit($event)">
+        </app-datatable-actions>
         <app-datatable
                 [dataset]="datasetList | datasetByName:datasetSelected"
                 [instance]="instance"
diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.spec.ts b/client/src/app/instance/search/components/result/datatable-tab.component.spec.ts
index 7705a42bee417a62090da3bbc6dceea580550981..3d261b62cf37b9689007c61b7de1a748793b5651 100644
--- a/client/src/app/instance/search/components/result/datatable-tab.component.spec.ts
+++ b/client/src/app/instance/search/components/result/datatable-tab.component.spec.ts
@@ -6,7 +6,7 @@ import { AccordionModule } from 'ngx-bootstrap/accordion';
 
 import { DatatableTabComponent } from './datatable-tab.component';
 import { Attribute, Dataset, Instance } from '../../../../metamodel/models';
-import { SearchQueryParams } from '../../../store/models';
+import { SearchQueryParams, Criterion, ConeSearch } from '../../../store/models';
 import { DatasetByNamePipe } from '../../../../shared/pipes/dataset-by-name.pipe';
 
 describe('[Instance][Search][Component][Result] DatatableTabComponent', () => {
@@ -24,6 +24,19 @@ describe('[Instance][Search][Component][Result] DatatableTabComponent', () => {
         @Input() selectedData: any[] = [];
     }
 
+    @Component({ selector: 'app-datatable-actions', template: '' })
+    class DatatableActionsStubComponent {
+        @Input() selectedData: any[] = [];
+        @Input() datasetSelected: string;
+        @Input() datasetList: Dataset[];
+        @Input() attributeList: Attribute[];
+        @Input() criteriaList: Criterion[];
+        @Input() outputList: number[];
+        @Input() coneSearch: ConeSearch;
+        @Input() dataLength: number;
+        @Input() sampRegistered: boolean;
+    }
+
     let component: DatatableTabComponent;
     let fixture: ComponentFixture<DatatableTabComponent>;
 
@@ -32,6 +45,7 @@ describe('[Instance][Search][Component][Result] DatatableTabComponent', () => {
             declarations: [
                 DatatableTabComponent,
                 DatatableStubComponent,
+                DatatableActionsStubComponent,
                 DatasetByNamePipe
             ],
             imports: [
diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.ts b/client/src/app/instance/search/components/result/datatable-tab.component.ts
index ff703b86206de32c28b2a9660077808926cd2eec..c70564ba46caa5d342e2c80c5516221d549dab58 100644
--- a/client/src/app/instance/search/components/result/datatable-tab.component.ts
+++ b/client/src/app/instance/search/components/result/datatable-tab.component.ts
@@ -10,7 +10,7 @@
 import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
 
 import { Instance, Attribute, Dataset } from 'src/app/metamodel/models';
-import { Pagination, SearchQueryParams } from 'src/app/instance/store/models';
+import { Pagination, SearchQueryParams, Criterion, ConeSearch } from 'src/app/instance/store/models';
 
 /**
  * @class
@@ -27,8 +27,11 @@ export class DatatableTabComponent {
     @Input() datasetList: Dataset[];
     @Input() attributeList: Attribute[];
     @Input() outputList: number[];
+    @Input() criteriaList: Criterion[];
+    @Input() coneSearch: ConeSearch;
     @Input() queryParams: SearchQueryParams;
     @Input() dataLength: number;
+    @Input() sampRegistered: boolean;
     @Input() data: any[];
     @Input() dataIsLoading: boolean;
     @Input() dataIsLoaded: boolean;
@@ -36,4 +39,5 @@ export class DatatableTabComponent {
     @Output() retrieveData: EventEmitter<Pagination> = new EventEmitter();
     @Output() addSelectedData: EventEmitter<number | string> = new EventEmitter();
     @Output() deleteSelectedData: EventEmitter<number | string> = new EventEmitter();
+    @Output() broadcast: EventEmitter<string> = new EventEmitter();
 }
diff --git a/client/src/app/instance/search/components/result/index.ts b/client/src/app/instance/search/components/result/index.ts
index f8e4657e1f14cc050b279326e6434fd79d50a862..fffbcf4e766b53c4b4788371155f5e08e7b22207 100644
--- a/client/src/app/instance/search/components/result/index.ts
+++ b/client/src/app/instance/search/components/result/index.ts
@@ -4,6 +4,7 @@ import { ReminderComponent } from './reminder.component';
 import { SampComponent } from './samp.component';
 import { UrlDisplayComponent } from './url-display.component';
 import { DatatableComponent } from './datatable.component';
+import { DatatableActionsComponent } from './datatable-actions.component';
 import { rendererComponents } from './renderer';
 
 export const resultComponents = [
@@ -13,5 +14,6 @@ export const resultComponents = [
     SampComponent,
     UrlDisplayComponent,
     DatatableComponent,
+    DatatableActionsComponent,
     rendererComponents
 ];
diff --git a/client/src/app/instance/search/containers/result.component.html b/client/src/app/instance/search/containers/result.component.html
index 93a2c7ac44fcdfbdb4dc13730bab79ae612d7c41..6ab41d2cd824b5b049c07165a48da4f90bdd5428 100644
--- a/client/src/app/instance/search/containers/result.component.html
+++ b/client/src/app/instance/search/containers/result.component.html
@@ -65,16 +65,19 @@
                 [instance]="instance | async"
                 [datasetList]="datasetList | async"
                 [attributeList]="attributeList | async | sortByOutputDisplay"
+                [criteriaList]="criteriaList | async"
                 [outputList]="outputList | async"
                 [queryParams]="queryParams | async"
                 [dataLength]="dataLength | async"
+                [sampRegistered]="sampRegistered | async"
                 [data]="data | async"
                 [dataIsLoading]="dataIsLoading | async"
                 [dataIsLoaded]="dataIsLoaded | async"
                 [selectedData]="selectedData | async"
                 (retrieveData)="retrieveData($event)"
                 (addSelectedData)="addSearchData($event)"
-                (deleteSelectedData)="deleteSearchData($event)">
+                (deleteSelectedData)="deleteSearchData($event)"
+                (broadcast)="broadcastVotable($event)">
             </app-datatable-tab>
         </ng-container>
     </div>
diff --git a/client/src/app/instance/search/containers/result.component.spec.ts b/client/src/app/instance/search/containers/result.component.spec.ts
index 16462a1f25a8131e4d79b1dc6dd559b616e0b53f..37153740f4e191821a4e55836b3d93e155a7b1ee 100644
--- a/client/src/app/instance/search/containers/result.component.spec.ts
+++ b/client/src/app/instance/search/containers/result.component.spec.ts
@@ -66,8 +66,11 @@ describe('[Instance][Search][Container] ResultComponent', () => {
         @Input() datasetList: Dataset[];
         @Input() attributeList: Attribute[];
         @Input() outputList: number[];
+        @Input() criteriaList: Criterion[];
+        @Input() coneSearch: ConeSearch;
         @Input() queryParams: SearchQueryParams;
         @Input() dataLength: number;
+        @Input() sampRegistered: boolean;
         @Input() data: any[];
         @Input() dataIsLoading: boolean;
         @Input() dataIsLoaded: boolean;
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index 84b7f5565f820eb0e18993c3fd967f7dd71b3b29..bfb8594e449030fea934eab9a1143c8ead325adb 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -55,6 +55,7 @@ import { sharedPipes } from './pipes';
         CommonModule,
         FormsModule,
         ReactiveFormsModule,
+        BsDropdownModule,
         ModalModule,
         AccordionModule,
         PopoverModule,
diff --git a/server/app/dependencies.php b/server/app/dependencies.php
index 2ba1d1681c1f8c71cb792a2c0ff90614ef782108..9fe363d692e79627b5dc6aea9e37acf9bce6371c 100644
--- a/server/app/dependencies.php
+++ b/server/app/dependencies.php
@@ -203,7 +203,7 @@ $container->set('App\Action\SearchAction', function (ContainerInterface $c) {
 $container->set('App\Action\ArchiveAction', function (ContainerInterface $c) {
     $anisQueryBuilder = (new App\Search\Query\AnisQueryBuilder())
         ->addQueryPart(new App\Search\Query\From())
-        ->addQueryPart(new App\Search\Query\SelectFile())
+        ->addQueryPart(new App\Search\Query\Select())
         ->addQueryPart(new App\Search\Query\ConeSearch())
         ->addQueryPart(new App\Search\Query\Where(new App\Search\Query\Operator\OperatorFactory()))
         ->addQueryPart(new App\Search\Query\Order())
diff --git a/server/src/Action/ArchiveAction.php b/server/src/Action/ArchiveAction.php
index 431a3648685b4d5ae588af229e5448ab0586a0ed..0b43917b15cb20be01cf249365fb84c304e6bbf4 100644
--- a/server/src/Action/ArchiveAction.php
+++ b/server/src/Action/ArchiveAction.php
@@ -150,8 +150,8 @@ final class ArchiveAction extends AbstractAction
         while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
             foreach ($attributesSelected as $attribute) {
                 $attributeLabel = $attribute->getLabel();
-                $filePath = $this->dataPath . $dataset->getDataPath() . DIRECTORY_SEPARATOR . $row[$attributeLabel];
-                if (file_exists($filePath)) {
+                $filePath = $this->dataPath . $dataset->getFullDataPath() . DIRECTORY_SEPARATOR . $row[$attributeLabel];
+                if (file_exists($filePath) && is_file($filePath)) {
                     $zip->addFile($filePath, $row[$attributeLabel]);
                 }
             }
diff --git a/server/src/Search/Query/SelectFile.php b/server/src/Search/Query/SelectFile.php
deleted file mode 100644
index 24d71445599a30058f1052b04043752e1fb71fa5..0000000000000000000000000000000000000000
--- a/server/src/Search/Query/SelectFile.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-/*
- * This file is part of Anis Server.
- *
- * (c) Laboratoire d'Astrophysique de Marseille / CNRS
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-declare(strict_types=1);
-
-namespace App\Search\Query;
-
-use App\Entity\Dataset;
-
-/**
- * Represents the Anis Select File attributes Query Part
- *
- * @author François Agneray <francois.agneray@lam.fr>
- * @package App\Search\Query
- */
-class SelectFile extends AbstractQueryPart
-{
-    /**
-     * Adds the select clause to the request and set only attribute with search_flag = FILE
-     *
-     * @param AnisQueryBuilder $anisQueryBuilder Represents the query being built
-     * @param Dataset          $dataset      Represents the requested dataset
-     * @param string[]         $queryParams  The query params of the url (after ?)
-     */
-    public function __invoke(AnisQueryBuilder $anisQueryBuilder, Dataset $dataset, array $queryParams): void
-    {
-        if ($queryParams['a'] === 'all') {
-            $listOfIds = array_map(fn($attribute) => $attribute->getId(), $dataset->getAttributes());
-        } else {
-            $listOfIds = explode(';', $queryParams['a']);
-        }
-
-        $columns = array();
-        $attributes = array();
-        foreach ($listOfIds as $id) {
-            $attribute = $this->getAttribute($dataset, (int) $id);
-            if ($attribute->getSearchFlag() === 'FILE') {
-                $columns[] = $dataset->getTableRef() . '.' . $attribute->getName() . ' as ' . $attribute->getLabel();
-                $attributes[] = $attribute;
-            }
-        }
-        $anisQueryBuilder->getDoctrineQueryBuilder()->select($columns);
-        $anisQueryBuilder->setAttributesSelected($attributes);
-    }
-}