feat: Unarchive destination select (#26)
* feat: Unarchive destination select * fix: Check file conflict on unarchivepull/3756/head
parent
aa8ca032f5
commit
1879a62423
|
@ -180,7 +180,7 @@ export async function archive(url, name, format, ...files) {
|
|||
}
|
||||
|
||||
export async function unarchive(path, name, override) {
|
||||
const to = encodeURIComponent(removePrefix(name));
|
||||
const to = removePrefix(name);
|
||||
const action = `unarchive`;
|
||||
const url = `${path}?action=${action}&destination=${to}&override=${override}`;
|
||||
return resourceAction(url, "PATCH");
|
||||
|
|
|
@ -5,14 +5,21 @@
|
|||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<p>{{ $t("prompts.unarchiveMessage") }}</p>
|
||||
<input
|
||||
class="input input--block"
|
||||
v-focus
|
||||
type="text"
|
||||
@keyup.enter="submit"
|
||||
v-model.trim="name"
|
||||
/>
|
||||
<form ref="unarchiveForm">
|
||||
<p>{{ $t("prompts.unarchiveFolderNameMessage") }}</p>
|
||||
<input
|
||||
class="input input--block"
|
||||
v-focus
|
||||
type="text"
|
||||
@keyup.enter="submit"
|
||||
v-model.trim="name"
|
||||
required
|
||||
/>
|
||||
</form>
|
||||
|
||||
<p>{{ $t("prompts.unarchiveDestinationLocationMessage") }}</p>
|
||||
<file-list @update:selected="(val) => (dest = val)"></file-list>
|
||||
|
||||
<p v-if="overwriteAvailable">
|
||||
<input type="checkbox" v-model="overwriteExisting" />
|
||||
{{ $t("prompts.unarchiveOverwriteExisting") }}
|
||||
|
@ -43,14 +50,17 @@
|
|||
|
||||
<script>
|
||||
import { mapState, mapGetters } from "vuex";
|
||||
import FileList from "./FileList";
|
||||
import { files as api } from "@/api";
|
||||
import buttons from "@/utils/buttons";
|
||||
|
||||
export default {
|
||||
name: "rename",
|
||||
components: { FileList },
|
||||
data: function () {
|
||||
return {
|
||||
overwriteExisting: false,
|
||||
dest: null,
|
||||
name: "",
|
||||
};
|
||||
},
|
||||
|
@ -76,10 +86,12 @@ export default {
|
|||
this.$store.commit("closeHovers");
|
||||
},
|
||||
submit: async function () {
|
||||
if (!this.$refs.unarchiveForm.reportValidity()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let item = this.req.items[this.selected[0]];
|
||||
let uri = this.isFiles ? this.$route.path + "/" : "/";
|
||||
let dst = uri + this.name;
|
||||
dst = dst.replace("//", "/");
|
||||
let dst = this.dest + encodeURIComponent(this.name);
|
||||
|
||||
try {
|
||||
buttons.loading("unarchive");
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "الحجم",
|
||||
"skipTrashMessage": "تخطى سلة المهملات واحذف فورا",
|
||||
"unarchive": "حذف من الأرشيف",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "اختر اسم المجلد الوجهة:",
|
||||
"unarchiveOverwriteExisting": "الكتابة فوق الملفات الموجودة",
|
||||
"unsavedChanges": "قد لا يتم حفظ التغييرات التي قمت بها. هل تريد مغادرة الصفحة؟",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Size",
|
||||
"skipTrashMessage": "Skip trash bin and delete immediately",
|
||||
"unarchive": "Unarchive",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Choose the destination folder name:",
|
||||
"unarchiveOverwriteExisting": "Overwrite existing files",
|
||||
"unsavedChanges": "Changes that you made may not be saved. Leave page?",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Tamaño",
|
||||
"skipTrashMessage": "Omitir papelera y eliminar inmediatamente",
|
||||
"unarchive": "Desarchiva",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Elige el nombre de la carpeta de destino:",
|
||||
"unarchiveOverwriteExisting": "Sobrescribir archivos existentes",
|
||||
"unsavedChanges": "Los cambios que realizaste podrían no guardarse. ¿Abandonar página?",
|
||||
|
@ -282,7 +284,7 @@
|
|||
"settings": "Ajustes",
|
||||
"signup": "Registrate",
|
||||
"siteSettings": "Ajustes del sitio",
|
||||
"tmpDir": "Temporary folder",
|
||||
"tmpDir": "Carpeta temporal",
|
||||
"trashBin": "Papelera"
|
||||
},
|
||||
"success": {
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Tamaño",
|
||||
"skipTrashMessage": "Omitir papelera y eliminar inmediatamente",
|
||||
"unarchive": "Desarchiva",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Elige el nombre de la carpeta de destino:",
|
||||
"unarchiveOverwriteExisting": "Sobrescribir archivos existentes",
|
||||
"unsavedChanges": "Los cambios que realizaste podrían no guardarse. ¿Abandonar página?",
|
||||
|
@ -282,7 +284,7 @@
|
|||
"settings": "Ajustes",
|
||||
"signup": "Registrate",
|
||||
"siteSettings": "Ajustes del sitio",
|
||||
"tmpDir": "Temporary folder",
|
||||
"tmpDir": "Carpeta temporal",
|
||||
"trashBin": "Papelera"
|
||||
},
|
||||
"success": {
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Tamaño",
|
||||
"skipTrashMessage": "Omitir papelera y eliminar inmediatamente",
|
||||
"unarchive": "Desarchiva",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Elige el nombre de la carpeta de destino:",
|
||||
"unarchiveOverwriteExisting": "Sobrescribir archivos existentes",
|
||||
"unsavedChanges": "Los cambios que realizaste podrían no guardarse. ¿Abandonar página?",
|
||||
|
@ -282,7 +284,7 @@
|
|||
"settings": "Ajustes",
|
||||
"signup": "Registrate",
|
||||
"siteSettings": "Ajustes del sitio",
|
||||
"tmpDir": "Temporary folder",
|
||||
"tmpDir": "Carpeta temporal",
|
||||
"trashBin": "Papelera"
|
||||
},
|
||||
"success": {
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Tamaño",
|
||||
"skipTrashMessage": "Omitir papelera y eliminar inmediatamente",
|
||||
"unarchive": "Desarchiva",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Elige el nombre de la carpeta de destino:",
|
||||
"unarchiveOverwriteExisting": "Sobrescribir archivos existentes",
|
||||
"unsavedChanges": "Los cambios que realizaste podrían no guardarse. ¿Abandonar página?",
|
||||
|
@ -282,7 +284,7 @@
|
|||
"settings": "Ajustes",
|
||||
"signup": "Registrate",
|
||||
"siteSettings": "Ajustes del sitio",
|
||||
"tmpDir": "Temporary folder",
|
||||
"tmpDir": "Carpeta temporal",
|
||||
"trashBin": "Papelera"
|
||||
},
|
||||
"success": {
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Taille",
|
||||
"skipTrashMessage": "Ignorer la corbeille et supprimer immédiatement",
|
||||
"unarchive": "Extraire",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Choisissez le nom du dossier de destination :",
|
||||
"unarchiveOverwriteExisting": "Écraser les fichiers existants",
|
||||
"unsavedChanges": "Les modifications que vous avez apportées peuvent ne pas être enregistrées. Quitter la page ?",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Ukuran",
|
||||
"skipTrashMessage": "Lewati keranjang sampah dan langsung hapus saja",
|
||||
"unarchive": "Buka arsip",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Pilih nama folder tujuan:",
|
||||
"unarchiveOverwriteExisting": "Timpa file yang sudah ada",
|
||||
"unsavedChanges": "Perubahan yang Anda buat mungkin tidak tersimpan. Tinggalkan halaman?",
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
"delete": "Ištrinti",
|
||||
"directorySizes": "Skaičiuoti katalogų dydžius",
|
||||
"download": "Atsisiųsti",
|
||||
"file": "File",
|
||||
"folder": "Folder",
|
||||
"file": "Failas",
|
||||
"folder": "Aplankas",
|
||||
"hideDotfiles": "Paslėpti konfigūracijos failus",
|
||||
"info": "Informacija",
|
||||
"more": "Daugiau",
|
||||
|
@ -170,6 +170,8 @@
|
|||
"size": "Dydis",
|
||||
"skipTrashMessage": "Ištrinti visam laikui",
|
||||
"unarchive": "Išarchyvuoti",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Pasirinkite aplanko pavadinimą:",
|
||||
"unarchiveOverwriteExisting": "Perrašyti esamus failus",
|
||||
"unsavedChanges": "Atlikti pakeitimai gali būti neišsaugoti. Norite išeiti iš puslapio?",
|
||||
|
@ -244,7 +246,7 @@
|
|||
"rules": "Taisyklės",
|
||||
"rulesHelp": "Čia galite apibrėžti konkrečiam naudotojui taikomų leidimų ir draudimų taisyklių rinkinį. Užblokuoti failai nebus rodomi sąrašuose ir nebus prieinami naudotojui.",
|
||||
"scope": "Apimtis",
|
||||
"setDateFormat": "Set exact date format",
|
||||
"setDateFormat": "Nustatyti datos formatą",
|
||||
"settingsUpdated": "Nustaytmai atnaujinti!",
|
||||
"shareDeleted": "Dalijimasis nutrauktas!",
|
||||
"shareDuration": "Dalijimosi trukmė",
|
||||
|
@ -282,7 +284,7 @@
|
|||
"settings": "Nustatymai",
|
||||
"signup": "Užsiregistruoti",
|
||||
"siteSettings": "Svetainės nustatymai",
|
||||
"tmpDir": "Temporary folder",
|
||||
"tmpDir": "Laikinas aplankas",
|
||||
"trashBin": "Šiukšlių dėžė"
|
||||
},
|
||||
"success": {
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Tamanho",
|
||||
"skipTrashMessage": "Pular lixeira e deletar imediatamente",
|
||||
"unarchive": "Desarquivar",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Escolha o nome da pasta de destino:",
|
||||
"unarchiveOverwriteExisting": "Sobrescrever arquivos existentes",
|
||||
"unsavedChanges": "As alterações que você fez podem não ser salvas. Sair da página?",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Tamanho",
|
||||
"skipTrashMessage": "Saltar o caixote do lixo e apagar imediatamente",
|
||||
"unarchive": "Desarquivar",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Escolha o nome da pasta de destino:",
|
||||
"unarchiveOverwriteExisting": "Sobrepor os ficheiros existentes",
|
||||
"unsavedChanges": "As alterações que fez poderão não ser guardadas. Deixar a página?",
|
||||
|
@ -282,7 +284,7 @@
|
|||
"settings": "Configurações",
|
||||
"signup": "Registar",
|
||||
"siteSettings": "Configurações do site",
|
||||
"tmpDir": "Temporary folder",
|
||||
"tmpDir": "Pasta temporária",
|
||||
"trashBin": "Caixote do lixo"
|
||||
},
|
||||
"success": {
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Размер",
|
||||
"skipTrashMessage": "Удалить, не сохраняя в корзину",
|
||||
"unarchive": "Разархивирование",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Выберите имя папки назначения:",
|
||||
"unarchiveOverwriteExisting": "Перезаписать существующие файлы",
|
||||
"unsavedChanges": "Невозможно сохранить внесённые изменения. Покинуть страницу?",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Boyut",
|
||||
"skipTrashMessage": "Çöp kutusunu atlayıp hemen sil",
|
||||
"unarchive": "Arşivden çıkar",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Hedef klasör adını seçin:",
|
||||
"unarchiveOverwriteExisting": "Mevcut dosyaların üzerine yaz",
|
||||
"unsavedChanges": "Yaptığınız değişiklikler kaydedilmeyecek. Çıkılsın mı?",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "Розмір",
|
||||
"skipTrashMessage": "Видалити без збереження в кошик",
|
||||
"unarchive": "Розархівування",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "Виберіть назву папки призначення:",
|
||||
"unarchiveOverwriteExisting": "Перезаписати наявні файли",
|
||||
"unsavedChanges": "Неможливо зберегти внесені зміни. Покинути сторінку?",
|
||||
|
|
|
@ -170,6 +170,8 @@
|
|||
"size": "大小",
|
||||
"skipTrashMessage": "跳过回收站并立即删除",
|
||||
"unarchive": "解压缩",
|
||||
"unarchiveDestinationLocationMessage": "Select the destination:",
|
||||
"unarchiveFolderNameMessage": "Choose folder name:",
|
||||
"unarchiveMessage": "选择目标文件夹名字:",
|
||||
"unarchiveOverwriteExisting": "覆盖现有文件",
|
||||
"unsavedChanges": "您所做的修改将不会被保存, 丢弃更改吗?",
|
||||
|
|
103
http/resource.go
103
http/resource.go
|
@ -277,7 +277,8 @@ func resourcePatchHandler(fileCache FileCache) handleFunc {
|
|||
|
||||
override := r.URL.Query().Get("override") == "true"
|
||||
rename := r.URL.Query().Get("rename") == "true"
|
||||
if !override && !rename {
|
||||
unarchive := action == "unarchive"
|
||||
if !override && !rename && !unarchive {
|
||||
if _, err = d.user.Fs.Stat(dst); err == nil {
|
||||
return http.StatusConflict, nil
|
||||
}
|
||||
|
@ -292,7 +293,11 @@ func resourcePatchHandler(fileCache FileCache) handleFunc {
|
|||
}
|
||||
|
||||
err = d.RunHook(func() error {
|
||||
return patchAction(r.Context(), action, src, dst, d, fileCache)
|
||||
if unarchive {
|
||||
return unarchiveAction(src, dst, d, override)
|
||||
} else {
|
||||
return patchAction(r.Context(), action, src, dst, d, fileCache)
|
||||
}
|
||||
}, action, src, dst, d.user)
|
||||
|
||||
return errToStatus(err), err
|
||||
|
@ -441,53 +446,75 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach
|
|||
}
|
||||
|
||||
return fileutils.MoveFile(d.user.Fs, src, dst)
|
||||
case "unarchive":
|
||||
if !d.user.Perm.Create {
|
||||
return errors.ErrPermissionDenied
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported action %s: %w", action, errors.ErrInvalidRequestParams)
|
||||
}
|
||||
}
|
||||
|
||||
src = d.user.FullPath(path.Clean("/" + src))
|
||||
dst = d.user.FullPath(path.Clean("/" + dst))
|
||||
func unarchiveAction(src, dst string, d *data, overwrite bool) error {
|
||||
if !d.user.Perm.Create {
|
||||
return errors.ErrPermissionDenied
|
||||
}
|
||||
|
||||
arch, err := archiver.ByExtension(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
src = d.user.FullPath(path.Clean("/" + src))
|
||||
dst = d.user.FullPath(path.Clean("/" + dst))
|
||||
|
||||
// if we reach this place when overwrite is needed,
|
||||
// it means that override was selected
|
||||
switch a := arch.(type) {
|
||||
case *archiver.Rar:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.Tar:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.TarBz2:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.TarGz:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.TarLz4:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.TarSz:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.TarXz:
|
||||
a.OverwriteExisting = true
|
||||
case *archiver.Zip:
|
||||
a.OverwriteExisting = true
|
||||
}
|
||||
arch, err := archiver.ByExtension(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
unarchiver, ok := arch.(archiver.Unarchiver)
|
||||
if !ok {
|
||||
return errors.ErrInvalidRequestParams
|
||||
}
|
||||
switch a := arch.(type) {
|
||||
case *archiver.Rar:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.Tar:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.TarBz2:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.TarGz:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.TarLz4:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.TarSz:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.TarXz:
|
||||
a.OverwriteExisting = overwrite
|
||||
case *archiver.Zip:
|
||||
a.OverwriteExisting = overwrite
|
||||
}
|
||||
|
||||
unarchiver, ok := arch.(archiver.Unarchiver)
|
||||
if ok {
|
||||
err = unarchiver.Unarchive(src, dst)
|
||||
if err != nil {
|
||||
return errors.ErrInvalidRequestParams
|
||||
}
|
||||
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported action %s: %w", action, errors.ErrInvalidRequestParams)
|
||||
}
|
||||
|
||||
decompressor, ok := arch.(archiver.Decompressor)
|
||||
if ok {
|
||||
reader, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dst, err := os.OpenFile(dst, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = decompressor.Decompress(reader, dst)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return errors.ErrInvalidRequestParams
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.ErrInvalidRequestParams
|
||||
}
|
||||
|
||||
func archiveHandler(r *http.Request, d *data) (int, error) {
|
||||
|
|
Loading…
Reference in New Issue