feat(thumb blob path): support magic variables in thumb blob path (#3030) (#317)

* feat(thumb blob path): support magic variables in thumb blob path

* Update dashboard.json
This commit is contained in:
Darren Yu 2025-11-12 13:49:41 +08:00 committed by GitHub
parent 25c0fd5ae1
commit 51bbced0b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 97 additions and 41 deletions

View File

@ -450,8 +450,8 @@
"proxyPolicyListDes": "Mehrfach auswählbar. Wenn aktiviert, werden Dateien, deren Speicherrichtlinie keine native Generierung unterstützt, ihre Miniaturansichten von Cloudreve proxy-generiert.",
"thumbWidth": "Max. Breite",
"thumbHeight": "Max. Höhe",
"thumbSuffix": "Blob-Datei-Suffix",
"thumbSuffixDes": "Das Suffix, das an den ursprünglichen Blob-Dateinamen für die generierte Miniaturansicht angehängt wird, ",
"thumbPath": "Miniaturansicht-Pfad",
"thumbPathDes": "Der vollständige Dateipfad für die Generierung von Miniaturansicht-Blobs. Sie können <0>magische Variablen</0> verwenden. Stellen Sie sicher, dass er absolut eindeutig ist, auch bei mehreren Uploads derselben Datei in kurzer Zeit.",
"thumbFormat": "Bildformat",
"thumbFormatDes": "Bevorzugtes Bildformat, wenn der Generator es nicht unterstützt, wird es automatisch auf jpg-Format herabgestuft.",
"thumbQuality": "Qualität",
@ -932,7 +932,10 @@
"hour": "Stunde",
"minute": "Minute",
"second": "Sekunde",
"path": "Der ursprüngliche Pfad beim Hochladen der Datei durch den Benutzer"
"path": "Der ursprüngliche Pfad beim Hochladen der Datei durch den Benutzer",
"blobPath": "Der vollständige Pfad der Datei-Blob",
"blobName": "Der Name der Datei-Blob",
"blobNameNoext": "Datei-Blob-Name ohne Erweiterung"
},
"storageBucket": "Speicher-Bucket",
"wanSiteURLDes": "Bevor Sie diese Richtlinie verwenden, stellen Sie bitte sicher, dass die Adresse, die Sie in Grundeinstellungen - Site-Informationen - Site-URL eingegeben haben, mit der tatsächlichen Adresse übereinstimmt und <0>ordnungsgemäß über WAN zugänglich</0> ist.",

View File

@ -449,8 +449,8 @@
"proxyPolicyListDes": "Multi-selectable. If enabled, files whose storage policy does not support native generation, its thumbnails will be proxy generated by the Cloudreve.",
"thumbWidth": "Max width",
"thumbHeight": "Max height",
"thumbSuffix": "Blob file suffix",
"thumbSuffixDes": "The suffix appended to the original Blob file name for the generated thumbnail, ",
"thumbPath": "Image path",
"thumbPathDes": "The complete file path for generating thumbnail Blobs, you can use <0>magic variables</0>, make sure it's absolutely unique, even for multiple uploads of the same file in a short time.",
"thumbFormat": "Image format",
"thumbFormatDes": "Preferred image format, if the generator does not support it, it will automatically downgrade to jpg format.",
"thumbQuality": "Quality",
@ -933,7 +933,10 @@
"hour": "Hour",
"minute": "Minute",
"second": "Second",
"path": "The initial path while user uploads the file"
"path": "The initial path while user uploads the file",
"blobPath": "The complete path of file Blob",
"blobName": "File Blob name",
"blobNameNoext": "File Blob name without ext"
},
"storageBucket": "Storage bucket",
"wanSiteURLDes": "Before using this policy, please make sure that the address you entered in Basic Settings - Site Information - Site URL matches the actual address and <0>can be accessed properly by WAN</0>.",

View File

@ -450,8 +450,8 @@
"proxyPolicyListDes": "Multi-seleccionable. Si está habilitado, archivos cuya política de almacenamiento no soporta generación nativa, sus miniaturas serán generadas por proxy por Cloudreve.",
"thumbWidth": "Ancho máximo",
"thumbHeight": "Altura máxima",
"thumbSuffix": "Sufijo de archivo Blob",
"thumbSuffixDes": "El sufijo agregado al nombre de archivo Blob original para la miniatura generada, ",
"thumbPath": "Ruta de Miniatura",
"thumbPathDes": "La ruta completa del archivo para generar Blob de miniatura, puedes usar <0>variables mágicas</0>, asegúrate de que sea absolutamente única, incluso para múltiples subidas del mismo archivo en poco tiempo.",
"thumbFormat": "Formato de imagen",
"thumbFormatDes": "Formato de imagen preferido, si el generador no lo soporta, automáticamente se degradará al formato jpg.",
"thumbQuality": "Calidad",
@ -932,7 +932,10 @@
"hour": "Hora",
"minute": "Minuto",
"second": "Segundo",
"path": "La ruta inicial mientras el usuario sube el archivo"
"path": "La ruta inicial mientras el usuario sube el archivo",
"blobPath": "La ruta completa del archivo Blob",
"blobName": "El nombre del archivo Blob",
"blobNameNoext": "Nombre del archivo Blob sin extensión"
},
"storageBucket": "Bucket de almacenamiento",
"wanSiteURLDes": "Antes de usar esta política, asegúrate de que la dirección que ingresaste en Configuración Básica - Información del Sitio - URL del Sitio coincida con la dirección real y <0>pueda ser accedida apropiadamente por WAN</0>.",

View File

@ -450,8 +450,8 @@
"proxyPolicyListDes": "Multi-sélectionnable. Si activé, les fichiers dont la politique de stockage ne prend pas en charge la génération native, ses miniatures seront générées par proxy par Cloudreve.",
"thumbWidth": "Largeur maximale",
"thumbHeight": "Hauteur maximale",
"thumbSuffix": "Suffixe du fichier Blob",
"thumbSuffixDes": "Le suffixe ajouté au nom du fichier Blob original pour la miniature générée, ",
"thumbPath": "Chemin de Miniature",
"thumbPathDes": "Le chemin complet du fichier pour générer des Blob de miniature, vous pouvez utiliser des <0>variables magiques</0>, assurez-vous qu'il soit absolument unique, même pour plusieurs uploads du même fichier en peu de temps.",
"thumbFormat": "Format d'image",
"thumbFormatDes": "Format d'image préféré, si le générateur ne le prend pas en charge, il se dégradrera automatiquement au format jpg.",
"thumbQuality": "Qualité",
@ -932,7 +932,10 @@
"hour": "Heure",
"minute": "Minute",
"second": "Seconde",
"path": "Le chemin initial lors de l'upload du fichier par l'utilisateur"
"path": "Le chemin initial lors de l'upload du fichier par l'utilisateur",
"blobPath": "Le chemin complet du fichier Blob",
"blobName": "Le nom du fichier Blob",
"blobNameNoext": "Nom du fichier Blob sans extension"
},
"storageBucket": "Bucket de stockage",
"wanSiteURLDes": "Avant d'utiliser cette politique, assurez-vous que l'adresse que vous avez saisie dans Paramètres de base - Informations du site - URL du site correspond à l'adresse réelle et <0>peut être accessible correctement par WAN</0>.",

View File

@ -450,8 +450,8 @@
"proxyPolicyListDes": "Multi-selezionabile. Se abilitato, i file la cui policy di archiviazione non supporta la generazione nativa, le loro miniature saranno generate tramite proxy da Cloudreve.",
"thumbWidth": "Larghezza massima",
"thumbHeight": "Altezza massima",
"thumbSuffix": "Suffisso file blob",
"thumbSuffixDes": "Il suffisso aggiunto al nome del file Blob originale per la miniatura generata, ",
"thumbPath": "Percorso Miniatura",
"thumbPathDes": "Il percorso completo del file per generare Blob di miniatura, puoi usare <0>variabili magiche</0>, assicurati che sia assolutamente univoco, anche per caricamenti multipli dello stesso file in poco tempo.",
"thumbFormat": "Formato immagine",
"thumbFormatDes": "Formato immagine preferito, se il generatore non lo supporta, verrà automaticamente retrocesso al formato jpg.",
"thumbQuality": "Qualità",
@ -932,7 +932,10 @@
"hour": "Ora",
"minute": "Minuto",
"second": "Secondo",
"path": "Il percorso iniziale durante il caricamento del file da parte dell'utente"
"path": "Il percorso iniziale durante il caricamento del file da parte dell'utente",
"blobPath": "Il percorso completo del file Blob",
"blobName": "Il nome del file Blob",
"blobNameNoext": "Nome del file Blob senza estensione"
},
"storageBucket": "Bucket di archiviazione",
"wanSiteURLDes": "Prima di utilizzare questa politica, assicurati che l'indirizzo inserito in Impostazioni di base - Informazioni sito - URL del sito corrisponda all'indirizzo effettivo e <0>possa essere accessibile correttamente dalla WAN</0>.",

View File

@ -449,8 +449,8 @@
"proxyPolicyListDes": "複数選択可。選択した場合、ストレージポリシーがネイティブのサムネイル生成をサポートしていないタイプは、Cloudreve代理によって生成されます。",
"thumbWidth": "最大幅",
"thumbHeight": "最大高さ",
"thumbSuffix": "Blobファイル拡張子",
"thumbSuffixDes": "生成されたサムネイルBlobは、元のBlobに追加されたサフィックスです。",
"thumbPath": "サムネイルパス",
"thumbPathDes": "サムネイルBlobを生成する完全なファイルパス。<0>マジック変数</0>を使用できます。短時間に同じファイルを複数回アップロードした場合でも、絶対的な一意性を確保する必要があります。",
"thumbFormat": "サムネイル形式",
"thumbFormatDes": "優先使用するサムネイル形式。ジェネレーターがサポートしていない場合、jpg形式に自動的に降格します。",
"thumbQuality": "画像品質",
@ -933,7 +933,10 @@
"hour": "時",
"minute": "分",
"second": "秒",
"path": "ユーザーファイルアップロード時の初期パス"
"path": "ユーザーファイルアップロード時の初期パス",
"blobPath": "ファイルBlobの完全なパス",
"blobName": "ファイルBlobの名前",
"blobNameNoext": "拡張子なしファイルBlob名"
},
"storageBucket": "ストレージ",
"wanSiteURLDes": "このストレージポリシーを使用する前に、「パラメーター設定 - サイト情報 - サイトURL」に入力したアドレスが実際と一致し、かつ<0>外部ネットワークからアクセス可能であることを確認してください</0>。",

View File

@ -449,8 +449,8 @@
"proxyPolicyListDes": "다중 선택 가능. 선택하면 저장소 정책에서 네이티브 썸네일 생성을 지원하지 않는 유형은 Cloudreve에서 프록시 생성됩니다.",
"thumbWidth": "최대 너비",
"thumbHeight": "최대 높이",
"thumbSuffix": "Blob 파일 접미사",
"thumbSuffixDes": "생성된 썸네일 Blob이 원본 Blob에 대해 추가되는 접미사",
"thumbPath": "썸네일 경로",
"thumbPathDes": "썸네일 Blob을 생성하는 완전한 파일 경로로, <0>매직 변수</0>를 사용할 수 있으며, 짧은 시간 내에 같은 파일을 여러 번 업로드하는 경우에도 절대적으로 고유해야 합니다.",
"thumbFormat": "썸네일 형식",
"thumbFormatDes": "우선 사용할 썸네일 형식으로, 생성기에서 지원하지 않으면 자동으로 jpg 형식으로 다운그레이드됩니다.",
"thumbQuality": "이미지 품질",
@ -933,7 +933,10 @@
"hour": "시간",
"minute": "분",
"second": "초",
"path": "사용자가 파일을 업로드할 때의 초기 경로"
"path": "사용자가 파일을 업로드할 때의 초기 경로",
"blobPath": "파일 Blob의 완전한 경로",
"blobName": "파일 Blob의 이름",
"blobNameNoext": "확장자 없는 파일 Blob 이름"
},
"storageBucket": "스토리지 공간",
"wanSiteURLDes": "이 스토리지 정책을 사용하기 전에 매개변수 설정 - 사이트 정보 - 사이트 URL에 입력한 주소가 실제와 일치하고 <0>외부 네트워크에서 정상적으로 액세스할 수 있는지</0> 확인하세요.",

View File

@ -450,8 +450,8 @@
"proxyPolicyListDes": "Multi-selecionável. Se habilitado, arquivos cuja política de armazenamento não suporta geração nativa, suas miniaturas serão geradas por proxy pelo Cloudreve.",
"thumbWidth": "Largura máxima",
"thumbHeight": "Altura máxima",
"thumbSuffix": "Sufixo do arquivo Blob",
"thumbSuffixDes": "O sufixo anexado ao nome do arquivo Blob original para a miniatura gerada, ",
"thumbPath": "Caminho da Miniatura",
"thumbPathDes": "O caminho completo do arquivo para gerar Blob de miniatura, você pode usar <0>variáveis mágicas</0>, certifique-se de que seja absolutamente único, mesmo para múltiplos uploads do mesmo arquivo em pouco tempo.",
"thumbFormat": "Formato da imagem",
"thumbFormatDes": "Formato de imagem preferido, se o gerador não suportar, fará downgrade automaticamente para formato jpg.",
"thumbQuality": "Qualidade",
@ -932,7 +932,10 @@
"hour": "Hora",
"minute": "Minuto",
"second": "Segundo",
"path": "O caminho inicial enquanto o usuário envia o arquivo"
"path": "O caminho inicial enquanto o usuário envia o arquivo",
"blobPath": "O caminho completo do arquivo Blob",
"blobName": "O nome do arquivo Blob",
"blobNameNoext": "Nome do arquivo Blob sem extensão"
},
"storageBucket": "Bucket de armazenamento",
"wanSiteURLDes": "Antes de usar esta política, certifique-se de que o endereço inserido em Configurações Básicas - Informações do Site - URL do Site corresponde ao endereço real e <0>pode ser acessado adequadamente pela WAN</0>.",

View File

@ -450,8 +450,8 @@
"proxyPolicyListDes": "Можно выбрать несколько. После выбора типы, для которых стратегия хранения не поддерживает нативную генерацию миниатюр, будут генерироваться через прокси Cloudreve.",
"thumbWidth": "Максимальная ширина",
"thumbHeight": "Максимальная высота",
"thumbSuffix": "Суффикс Blob-файла",
"thumbSuffixDes": "Суффикс, добавляемый к созданному Blob миниатюры относительно исходного Blob,",
"thumbPath": "Путь Миниатюры",
"thumbPathDes": "Полный путь к файлу для генерации Blob миниатюры, можно использовать <0>магические переменные</0>. Должен быть абсолютно уникальным, даже при многократной загрузке одного и того же файла за короткое время.",
"thumbFormat": "Формат миниатюры",
"thumbFormatDes": "Предпочтительный формат миниатюры. Если генератор не поддерживает его, автоматически переключится на формат jpg.",
"thumbQuality": "Качество изображения",
@ -934,7 +934,10 @@
"hour": "Час",
"minute": "Минута",
"second": "Секунда",
"path": "Исходный путь файла при загрузке пользователем"
"path": "Исходный путь файла при загрузке пользователем",
"blobPath": "Полный путь к файлу Blob",
"blobName": "Имя файла Blob",
"blobNameNoext": "Имя файла Blob без расширения"
},
"storageBucket": "Хранилище",
"wanSiteURLDes": "Перед использованием этой политики хранения убедитесь, что URL сайта в разделе Настройки параметров - Информация о сайте соответствует действительности и <0>доступен из внешней сети</0>.",

View File

@ -449,8 +449,8 @@
"proxyPolicyListDes": "可多选。选中后,存储策略不支持原生生成缩略图的类型会由 Cloudreve 代理生成。",
"thumbWidth": "最大宽度",
"thumbHeight": "最大高度",
"thumbSuffix": "Blob 文件后缀",
"thumbSuffixDes": "生成的缩略图 Blob 相对于原始 Blob 增加的后缀,",
"thumbPath": "缩略图路径",
"thumbPathDes": "生成缩略图 Blob 的完整文件路径,可以使用 <0>魔法变量</0>,需要确保为绝对唯一,即使在短时间内多次上传同一文件。",
"thumbFormat": "缩略图格式",
"thumbFormatDes": "优先使用的缩略图格式,如果生成器不支持,会自动降级为 jpg 格式。",
"thumbQuality": "图像质量",
@ -933,7 +933,10 @@
"hour": "小时",
"minute": "分钟",
"second": "秒",
"path": "用户上传文件时的初始路径"
"path": "用户上传文件时的初始路径",
"blobPath": "文件 Blob 的完整路径",
"blobName": "文件 Blob 的名称",
"blobNameNoext": "无扩展名的文件 Blob 名称"
},
"storageBucket": "存储空间",
"wanSiteURLDes": "在使用此存储策略前,请确保你在 参数设置 - 站点信息 - 站点URL 中填写的 地址与实际相符,并且 <0>能够被外网正常访问</0>。",

View File

@ -449,8 +449,8 @@
"proxyPolicyListDes": "可多選。選中後,儲存策略不支援原生生成縮圖的型別會由 Cloudreve 代理生成",
"thumbWidth": "最大寬度",
"thumbHeight": "最大高度",
"thumbSuffix": "Blob 檔案字尾",
"thumbSuffixDes": "生成的縮圖 Blob 相對於原始 Blob 增加的字尾,",
"thumbPath": "縮圖路徑",
"thumbPathDes": "生成縮圖 Blob 的完整檔案路徑,可以使用 <0>魔法變數</0>,需要確保為絕對唯一,即使在短時間內多次上傳同一檔案。",
"thumbFormat": "縮圖格式",
"thumbFormatDes": "優先使用的縮圖格式,如果生成器不支援,會自動降級為 jpg 格式。",
"thumbQuality": "影象質量",
@ -933,7 +933,10 @@
"hour": "小時",
"minute": "分鐘",
"second": "秒",
"path": "使用者上傳檔案時的初始路徑"
"path": "使用者上傳檔案時的初始路徑",
"blobPath": "檔案 Blob 的完整路徑",
"blobName": "檔案 Blob 的名稱",
"blobNameNoext": "無副檔名的檔案 Blob 名稱"
},
"storageBucket": "儲存空間",
"wanSiteURLDes": "在使用此儲存策略前,請確保你在 引數設定 - 站點資訊 - 站點URL 中填寫的 地址與實際相符,並且 <0>能夠被外網正常訪問</0>。",

View File

@ -1,6 +1,6 @@
import { Alert, Box, Collapse, FormControlLabel, Link, ListItemText, Stack, Switch, Typography } from "@mui/material";
import FormControl from "@mui/material/FormControl";
import { useContext } from "react";
import { useCallback, useContext, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { isTrueVal } from "../../../../session/utils.ts";
import { DenseFilledTextField, DenseSelect } from "../../../Common/StyledComponents.tsx";
@ -10,10 +10,18 @@ import { NoMarginHelperText, SettingSection, SettingSectionContent } from "../Se
import { SettingContext } from "../SettingWrapper.tsx";
import Extractors from "./Extractors.tsx";
import Generators from "./Generators.tsx";
import MagicVarDialog from "../../Common/MagicVarDialog";
import { thumbnailMagicVars } from "../../StoragePolicy/EditStoragePolicy/FormSections/magicVars.ts";
const Media = () => {
const { t } = useTranslation("dashboard");
const { formRef, setSettings, values } = useContext(SettingContext);
const [magicVarDialogOpen, setMagicVarDialogOpen] = useState(false);
const handleThumbMagicVarClick = useCallback((e: React.MouseEvent) => {
e.preventDefault();
setMagicVarDialogOpen(true);
}, []);
return (
<Box component={"form"} ref={formRef} onSubmit={(e) => e.preventDefault()}>
@ -56,7 +64,7 @@ const Media = () => {
/>
</FormControl>
</SettingForm>
<SettingForm title={t("settings.thumbSuffix")} lgWidth={5}>
<SettingForm title={t("settings.thumbPath")} lgWidth={5}>
<FormControl fullWidth>
<DenseFilledTextField
required
@ -68,9 +76,12 @@ const Media = () => {
}}
/>
<NoMarginHelperText>
{t("settings.notAppliedToNativeGenerator", {
prefix: t("settings.thumbSuffixDes"),
})}
<Trans
i18nKey="settings.notAppliedToNativeGenerator"
ns="dashboard"
values={{ prefix: t("settings.thumbPathDes") }}
components={[<Link href="#" onClick={handleThumbMagicVarClick} />]}
/>
</NoMarginHelperText>
</FormControl>
</SettingForm>
@ -143,6 +154,11 @@ const Media = () => {
</FormControl>
</SettingForm>
</SettingSectionContent>
<MagicVarDialog
open={magicVarDialogOpen}
onClose={() => setMagicVarDialogOpen(false)}
vars={thumbnailMagicVars}
/>
<Typography variant="subtitle1" gutterBottom sx={{ mt: 1 }}>
{t("settings.generators")}
</Typography>

View File

@ -18,10 +18,10 @@ export const commonMagicVars: MagicVar[] = [
{ name: "{hour}", value: "policy.magicVar.hour", example: "12" },
{ name: "{minute}", value: "policy.magicVar.minute", example: "00" },
{ name: "{second}", value: "policy.magicVar.second", example: "00" },
{ name: "{originname}", value: "policy.magicVar.originalFileName", example: "example.jpg" },
{ name: "{ext}", value: "policy.magicVar.extension", example: ".jpg" },
{ name: "{originname_without_ext}", value: "policy.magicVar.originFileNameNoext", example: "example" },
{ name: "{uuid}", value: "policy.magicVar.uuidV4", example: "550e8400-e29b-41d4-a716-446655440000" },
{ name: "{ext}", value: "policy.magicVar.extension", example: ".jpg" },
{ name: "{originname}", value: "policy.magicVar.originalFileName", example: "example.jpg" },
{ name: "{originname_without_ext}", value: "policy.magicVar.originFileNameNoext", example: "example" },
];
export const pathMagicVars: MagicVar[] = [
@ -30,3 +30,10 @@ export const pathMagicVars: MagicVar[] = [
];
export const fileMagicVars: MagicVar[] = [...commonMagicVars];
export const thumbnailMagicVars: MagicVar[] = [
...pathMagicVars,
{ name: "{blob_name}", value: "policy.magicVar.blobName", example: "a1b2c3d4_example.mp4" },
{ name: "{blob_name_without_ext}", value: "policy.magicVar.blobNameNoext", example: "abcd1234_example" },
{ name: "{blob_path}", value: "policy.magicVar.blobPath", example: "/data/i-m-physical-path/" },
];