fix filename bug
This commit is contained in:
+6
-5
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
return [
|
||||
'routes' => [
|
||||
['name' => 'page#main', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'page#zipDrop', 'url' => '/zipDrop', 'verb' => 'GET'],
|
||||
['name' => 'page#getFile', 'url' => '/getFile', 'verb' => 'GET']
|
||||
]
|
||||
'routes' => [
|
||||
['name' => 'page#main', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'page#zipDrop', 'url' => '/zipDrop', 'verb' => 'GET'],
|
||||
['name' => 'page#getFile', 'url' => '/getFile', 'verb' => 'GET'],
|
||||
['name' => 'page#getFileMetadata', 'url' => '/getFileMetadata', 'verb' => 'GET']
|
||||
]
|
||||
];
|
||||
|
||||
@@ -134,4 +134,97 @@ class PageController extends Controller {
|
||||
return new JsonResponse(['parameters' => $parameters, 'status' => 500]); // 500 Internal Server Error
|
||||
}
|
||||
}
|
||||
|
||||
// Nouvelle méthode pour récupérer les métadonnées du fichier
|
||||
#[NoCSRFRequired]
|
||||
#[NoAdminRequired]
|
||||
#[OpenAPI(OpenAPI::SCOPE_IGNORE)]
|
||||
#[FrontpageRoute(verb: 'GET', url: '/getFileMetadata')]
|
||||
public function getFileMetadata(): JsonResponse {
|
||||
$zipUrl = $this->request->getParam('url');
|
||||
|
||||
// Initialiser les paramètres de réponse
|
||||
$parameters = [
|
||||
'status' => 'error',
|
||||
'message' => '',
|
||||
'filename' => null,
|
||||
'mime' => null,
|
||||
'size' => null
|
||||
];
|
||||
|
||||
// Valider l'URL
|
||||
if (!$zipUrl || filter_var($zipUrl, FILTER_VALIDATE_URL) === false) {
|
||||
$parameters['message'] = 'Invalid URL';
|
||||
return new JsonResponse(['parameters' => $parameters], 400);
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialiser cURL pour une requête HEAD
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $zipUrl);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true); // Récupérer les en-têtes
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true); // Requête HEAD (pas de corps)
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
|
||||
// Exécuter la requête HEAD
|
||||
$headerResponse = curl_exec($ch);
|
||||
|
||||
// Gérer les erreurs cURL
|
||||
if (curl_errno($ch)) {
|
||||
$parameters['message'] = 'cURL error: ' . curl_error($ch);
|
||||
curl_close($ch);
|
||||
return new JsonResponse(['parameters' => $parameters], 500);
|
||||
}
|
||||
|
||||
// Récupérer le code HTTP
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode !== 200) {
|
||||
$parameters['message'] = "HTTP error: $httpCode";
|
||||
return new JsonResponse(['parameters' => $parameters], $httpCode);
|
||||
}
|
||||
|
||||
// Extraire Content-Disposition depuis les en-têtes
|
||||
$contentDisposition = '';
|
||||
if (preg_match('/Content-Disposition: (.+)/i', $headerResponse, $matches)) {
|
||||
$contentDisposition = $matches[1];
|
||||
}
|
||||
|
||||
// Extraire le nom du fichier depuis Content-Disposition
|
||||
$filename = basename(parse_url($zipUrl, PHP_URL_PATH)); // Nom par défaut
|
||||
if ($contentDisposition) {
|
||||
preg_match('/filename="?([^"]+)"?/i', $contentDisposition, $filenameMatches);
|
||||
if (!empty($filenameMatches[1])) {
|
||||
$filename = $filenameMatches[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Extraire d'autres métadonnées (optionnel)
|
||||
$contentType = '';
|
||||
if (preg_match('/Content-Type: (.+)/i', $headerResponse, $typeMatches)) {
|
||||
$contentType = $typeMatches[1];
|
||||
}
|
||||
|
||||
$contentLength = 0;
|
||||
if (preg_match('/Content-Length: (\d+)/i', $headerResponse, $lengthMatches)) {
|
||||
$contentLength = (int)$lengthMatches[1];
|
||||
}
|
||||
|
||||
// Construire la réponse de succès
|
||||
$parameters['status'] = 'success';
|
||||
$parameters['message'] = 'Metadata retrieved successfully';
|
||||
$parameters['filename'] = $filename;
|
||||
$parameters['mime'] = $contentType;
|
||||
$parameters['size'] = $contentLength;
|
||||
|
||||
return new JsonResponse(['parameters' => $parameters], 200);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$parameters['message'] = 'Exception: ' . $e->getMessage();
|
||||
return new JsonResponse(['parameters' => $parameters], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
-18
@@ -1,18 +1,53 @@
|
||||
<template>
|
||||
<div id="app" class="h-full w-full dark:bg-black/80 bg-white/80">
|
||||
<!-- Conteneur principal, ajustement en flex-row à partir de sm -->
|
||||
<div class="h-full w-full flex flex-col sm:flex-row">
|
||||
<!-- Mode normal -->
|
||||
<div v-if="!isTestMode" class="h-full w-full flex flex-col sm:flex-row">
|
||||
<!-- Première section -->
|
||||
<div
|
||||
class="w-full sm:w-1/3 max-sm:h-2/5 p-4 sm:m-6 sm:mr-0 rounded-xl dark:bg-NcBlack/40 bg-white/80">
|
||||
class="w-full sm:w-1/3 max-sm:h-2/5 p-4 sm:m-6 sm:mr-0 rounded-xl dark:bg-NcBlack/30 bg-white/80">
|
||||
<WebContentViewer :translate="translate" @file-upload="handleFileUpload" @dragEnded="toggleDragEnded" :zipUrl="zipUrl"/>
|
||||
</div>
|
||||
<!-- Deuxième section -->
|
||||
<div
|
||||
class="w-full sm:w-2/3 max-sm:h-3/5 p-4 sm:m-6 sm:ml-4 dark:bg-NcBlack bg-white rounded-xl">
|
||||
class="w-full sm:w-2/3 max-sm:h-3/5 p-4 sm:m-6 sm:ml-4 dark:bg-NcBlack/30 bg-white rounded-xl">
|
||||
<FileTable :file="sharedFile" :dragEnded="dragEnded" :translate="translate" @dragEnded="toggleDragEnded"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mode test -->
|
||||
<div v-if="isTestMode" class="h-full w-full p-4">
|
||||
<div class="bg-white dark:bg-NcBlack/30 rounded-xl p-6">
|
||||
<h1 class="text-2xl font-bold mb-4 text-gray-800 dark:text-white">🧪 Mode Test</h1>
|
||||
|
||||
<!-- Champ pour l'URL de test -->
|
||||
<div class="mb-4">
|
||||
<label for="testUrl" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
||||
URL de test :
|
||||
</label>
|
||||
<input
|
||||
id="testUrl"
|
||||
v-model="testUrl"
|
||||
type="text"
|
||||
class="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-NcBlack/50 text-gray-800 dark:text-white"
|
||||
placeholder="https://example.com/fichier.odt"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Bouton pour lancer le test -->
|
||||
<button
|
||||
@click="runTest"
|
||||
class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition"
|
||||
>
|
||||
Tester
|
||||
</button>
|
||||
|
||||
<!-- Résultats du test -->
|
||||
<div v-if="testResults" class="mt-6 p-4 bg-gray-100 dark:bg-NcBlack/20 rounded-md">
|
||||
<h2 class="font-semibold mb-2 text-gray-800 dark:text-white">Résultats :</h2>
|
||||
<pre class="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{ testResults }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -39,26 +74,74 @@ export default {
|
||||
},
|
||||
data() {
|
||||
let zipUrl = document.getElementById('archiveInfos').getAttribute('dataarchiveurl');
|
||||
//console.log(zipUrl)
|
||||
return {
|
||||
zipUrl,
|
||||
sharedFile: null,
|
||||
dragEnded: false,
|
||||
// Nouveaux champs pour le mode test
|
||||
isTestMode: false,
|
||||
testUrl: '',
|
||||
testResults: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleFileUpload(file) {
|
||||
this.sharedFile = file;
|
||||
},
|
||||
toggleDragEnded(){
|
||||
this.dragEnded = !this.dragEnded;
|
||||
this.sharedFile = null;
|
||||
},
|
||||
translate(id) {
|
||||
return i18next.t(id)
|
||||
},
|
||||
},
|
||||
}
|
||||
mounted() {
|
||||
// Vérifier si l'URL contient ?test=true
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
this.isTestMode = urlParams.get('test') === 'true';
|
||||
},
|
||||
methods: {
|
||||
handleFileUpload(file) {
|
||||
this.sharedFile = file;
|
||||
},
|
||||
toggleDragEnded() {
|
||||
this.dragEnded = !this.dragEnded;
|
||||
this.sharedFile = null;
|
||||
},
|
||||
translate(id) {
|
||||
return i18next.t(id);
|
||||
},
|
||||
// Nouvelle méthode pour exécuter les tests
|
||||
async runTest() {
|
||||
if (!this.testUrl) {
|
||||
this.testResults = "❌ Veuillez entrer une URL de test.";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.testResults = "⏳ Test en cours...";
|
||||
|
||||
// Tester la fonction getFilenameFromUrl
|
||||
const filename = await this.getFilenameFromUrl(this.testUrl);
|
||||
this.testResults = `✅ Nom2 du fichier extrait : ${filename}\n\n`;
|
||||
|
||||
// Tester la fonction loadZipContent (si applicable)
|
||||
// Note: Vous pouvez adapter cette partie pour tester d'autres fonctions
|
||||
// this.testResults += `Contenu chargé : ${JSON.stringify(this.zipContent, null, 2)}`;
|
||||
|
||||
} catch (error) {
|
||||
this.testResults = `❌ Erreur : ${error.message}`;
|
||||
console.error("Erreur lors du test :", error);
|
||||
}
|
||||
},
|
||||
// Fonction pour extraire le nom du fichier depuis une URL
|
||||
async getFilenameFromUrl(fileUrl) {
|
||||
try {
|
||||
const metadataUrl = OC.generateUrl('/apps/webtransfer/getFileMetadata?url=' + encodeURIComponent(fileUrl));
|
||||
const metadataResponse = await fetch(metadataUrl);
|
||||
const metadataJson = await metadataResponse.json();
|
||||
|
||||
const originalFileName = metadataJson.parameters.filename;
|
||||
console.log("Nom du fichier :", originalFileName);
|
||||
|
||||
return "originalFileName: " + originalFileName + " json:" + metadataJson;
|
||||
|
||||
} catch (error) {
|
||||
console.error("Erreur dans getFilenameFromUrl :", error);
|
||||
return "erreur" + error; //fileUrl.split('/').pop();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
@dragleave.prevent="onDragLeave($event)" @dragend="onDragEnd">
|
||||
|
||||
<div v-for="file in files" :key="file.filename"
|
||||
class="flex h-16 items-center dark:hover:bg-NcGray hover:bg-NcWhite rounded-lg border-b last:border-b-0 border-gray-300 cursor-pointer"
|
||||
class="flex h-16 items-center dark:hover:bg-NcGray/20 hover:bg-NcWhite rounded-lg border-b last:border-b-0 border-gray-300 cursor-pointer"
|
||||
@click="handleClickElem(file)">
|
||||
|
||||
<!-- Nom -->
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NcBreadcrumbs from '@nextcloud/vue/dist/Components/NcBreadcrumbs.js';
|
||||
import NcBreadcrumbs from '@nextcloud/vue/dist/Components/NcBreadcrumbs.js';
|
||||
import NcBreadcrumb from '@nextcloud/vue/dist/Components/NcBreadcrumb.js';
|
||||
import JSZip from 'jszip';
|
||||
import ChevronRightIcon from 'vue-material-design-icons/ChevronRight.vue';
|
||||
@@ -183,14 +183,18 @@ export default {
|
||||
methods: {
|
||||
async loadZipContent() {
|
||||
try {
|
||||
const metadataUrl = OC.generateUrl('/apps/webtransfer/getFileMetadata?url=' + encodeURIComponent(this.zipUrl));
|
||||
const metadataResponse = await fetch(metadataUrl);
|
||||
const metadataJson = await metadataResponse.json();
|
||||
const originalFileName = metadataJson.parameters.filename;
|
||||
|
||||
var baseUrl = OC.generateUrl('/apps/webtransfer/getFile');
|
||||
let fullUrl = baseUrl + '?url=' + encodeURIComponent(this.zipUrl);
|
||||
|
||||
let response = await fetch(fullUrl);
|
||||
let responseJson = await response.json();
|
||||
|
||||
const zipData = responseJson.parameters.data;
|
||||
const first10Chars = zipData.substring(0,4);
|
||||
|
||||
const first10Chars = zipData.substring(0,4);
|
||||
|
||||
if(this.mode === "zip") {
|
||||
// Check si le debut du fichier correspond a celui d'un zip
|
||||
@@ -268,9 +272,12 @@ export default {
|
||||
|
||||
try {
|
||||
let type = await fileTypeFromBuffer(uint8Array);
|
||||
const file = new File([uint8Array], 'file.' + type.ext, {type: type.mime});
|
||||
|
||||
const file = new File([uint8Array], originalFileName, { type: type.mime });
|
||||
|
||||
//const file = new File([uint8Array], 'file.' + type.ext, {type: type.mime});
|
||||
let entry = [{
|
||||
name: file.name,
|
||||
name: file.name,
|
||||
isDirectory: false,
|
||||
size: file.size,
|
||||
content: uint8Array, // Initialiser 'content' pour les fichiers
|
||||
|
||||
Reference in New Issue
Block a user