admin: Can gunzip files

This commit is contained in:
nemunaire 2024-03-17 15:03:30 +01:00
parent c082ee43d0
commit a0cd651dae
4 changed files with 83 additions and 3 deletions

View File

@ -37,6 +37,7 @@ func declareFilesRoutes(router *gin.RouterGroup) {
// Check
apiFilesRoutes.POST("/check", checkFile)
apiFilesRoutes.POST("/gunzip", gunzipFile)
}
func FileHandler(c *gin.Context) {
@ -266,3 +267,15 @@ func checkFile(c *gin.Context) {
c.JSON(http.StatusOK, true)
}
func gunzipFile(c *gin.Context) {
file := c.MustGet("file").(*fic.EFile)
err := file.GunzipFileOnDisk()
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()})
return
}
c.JSON(http.StatusOK, true)
}

View File

@ -1350,7 +1350,8 @@ angular.module("FICApp")
.controller("FilesListController", function($scope, File, $location, $http, $rootScope) {
$scope.files = File.query();
$scope.errfnd = 0;
$scope.errfnd = null;
$scope.errzip = null;
$scope.fields = ["id", "path", "name", "checksum", "size"];
$scope.clearFiles = function(id) {
@ -1359,6 +1360,21 @@ angular.module("FICApp")
$scope.files = [];
});
};
$scope.gunzipFile = function(f) {
f.gunzipWIP = true;
$http({
url: "api/files/" + f.id + "/gunzip",
method: "POST"
}).then(function(response) {
f.gunzipWIP = false;
f.err = true;
}, function(response) {
f.gunzipWIP = false;
$scope.inSync = false;
$scope.errzip += 1;
f.err = response.data.errmsg;
})
};
$scope.checksum = function(f) {
$http({
url: "api/files/" + f.id + "/check",
@ -1372,10 +1388,18 @@ angular.module("FICApp")
})
};
$scope.checksumAll = function() {
$scope.errfnd = 0;
$scope.errfnd = null;
angular.forEach($scope.files, function(file) {
$scope.checksum(file);
});
if ($scope.errfnd === null) $scope.errfnd = 0;
};
$scope.gunzipFiles = function() {
$scope.errzip = null;
angular.forEach($scope.files, function(file) {
$scope.gunzipFile(file);
});
if ($scope.errzip === null) $scope.errzip = 0;
};
$scope.show = function(f) {
$location.url("/exercices/" + f.idExercice);

View File

@ -1,13 +1,16 @@
<h2>
Fichiers
<small class="text-muted" ng-if="errfnd > 0"><span class="glyphicon glyphicon-exclamation-sign"></span> <ng-pluralize count="errfnd" when="{'one': '{} erreur trouvée', 'other': '{} erreurs trouvées'}"></ng-pluralize></small>
<button type="button" ng-click="checksumAll()" class="float-right btn btn-sm btn-secondary"><span class="glyphicon glyphicon-flash" aria-hidden="true"></span> Vérifier les fichiers</button>
<small class="text-muted" ng-if="errzip > 0"><span class="glyphicon glyphicon-exclamation-sign"></span> <ng-pluralize count="errzip" when="{'one': '{} décompression problématique', 'other': '{} décompressions problématiques'}"></ng-pluralize></small>
<button type="button" ng-click="checksumAll()" class="float-right btn btn-sm" ng-class="{'btn-secondary': errfnd === null, 'btn-success': errfnd === 0, 'btn-danger': errfnd > 0}"><span class="glyphicon glyphicon-flash" aria-hidden="true"></span> Vérifier les fichiers</button>
<button type="button" ng-click="gunzipFiles()" class="float-right btn btn-sm mx-1" ng-class="{'btn-secondary': errzip === null, 'btn-success': errzip === 0, 'btn-danger': errzip > 0}" title="Décompresse tous les fichiers compressés afin d'afficher la bonne taille au moment du téléchargement"><span class="glyphicon glyphicon-compressed" aria-hidden="true"></span> Gunzip</button>
</h2>
<p><input type="search" class="form-control" placeholder="Search" ng-model="query" autofocus></p>
<table class="table table-hover table-bordered table-striped table-sm">
<thead class="thead-dark">
<tr>
<th></th>
<th ng-repeat="field in fields">
{{ field }}
</th>
@ -15,6 +18,13 @@
</thead>
<tbody>
<tr ng-repeat="file in files | filter: query" ng-class="{'bg-danger': file.err !== undefined && file.err !== true}" ng-click="show(file)">
<td>
<button type="button" class="btn btn-sm btn-light" ng-click="$event.stopPropagation();checksum(file)"><span class="glyphicon glyphicon-flash" aria-hidden="true"></span></button>
<button type="button" class="btn btn-sm btn-light" ng-click="$event.stopPropagation();gunzipFile(file)" ng-disabled="file.gunzipWIP">
<span class="glyphicon glyphicon-compressed" aria-hidden="true" ng-if="!file.gunzipWIP"></span>
<div class="spinner-border spinner-border-sm" role="status" ng-if="file.gunzipWIP"></div>
</button>
</td>
<td ng-repeat="field in fields">
{{ file[field] }}
<span ng-if="field == 'id' && file.err !== undefined && file.err !== true" title="{{ file.err }}" class="glyphicon glyphicon-exclamation-sign"></span>

View File

@ -1,6 +1,7 @@
package fic
import (
"compress/gzip"
"crypto"
_ "crypto/sha1"
"encoding/hex"
@ -403,3 +404,35 @@ func (f *EFile) CheckFileOnDisk() error {
return nil
}
}
// GunzipFileOnDisk gunzip a compressed file.
func (f *EFile) GunzipFileOnDisk() error {
if !strings.HasSuffix(f.origin, ".gz") || strings.HasSuffix(f.origin, ".tar.gz") {
return nil
}
fdIn, err := os.Open(path.Join(FilesDir, f.Path+".gz"))
if err != nil {
return err
}
defer fdIn.Close()
fdOut, err := os.Create(path.Join(FilesDir, strings.TrimSuffix(f.Path, ".gz")))
if err != nil {
return err
}
defer fdOut.Close()
gunzipfd, err := gzip.NewReader(fdIn)
if err != nil {
return err
}
defer gunzipfd.Close()
_, err = io.Copy(fdOut, gunzipfd)
if err != nil {
return err
}
return nil
}