OnlyOffice конвертирует .xls/.doc/.ppt → .xlsx/.docx/.pptx при загрузке. UploadToFolderReplacing матчил по точному stem|ext (FindFilesByDedupKey), поэтому повторный oo dav upload FOLDER f.xls --replace не находил сохранённый f.xlsx и создавал второй файл (live: id 3799+3887, 3800+3888 в Banks/Caixa/extractos/).
Что сделано
EquivalentUploadExt / FindFilesByStemExt: матч по stem с учётом серверной конвертации (legacy ↔ OOXML: .xls/.doc/.ppt ↔ .xlsx/.docx/.pptx).
planUploadReplacement: выбирает выживающий файл и лишние дубликаты для замены.
UploadToFolderReplacing: при совпадении обновляет существующий файл по id (UpdateFile, id стабилен, нет окна удаления), удаляет лишние дубликаты; при отказе портала — fallback на conversion-aware delete + upload (один файл на stem в любом случае).
AssertNoFileConflict (--no-replace) использует тот же матчинг: .xls конфликтует с существующим .xlsx.
go test -race ./..., go vet ./..., gofmt -l — чисто.
PDF/XLSX-пути без изменений (exact-ext матч сохранён).
Открытый вопрос
В process env нет ONLYOFFICE_* — live-проверка на реальном портале не выполнена (offline-тесты зелёные). Требует проверки: конвертирует ли PUT /files/{id}/update payload .xls в .xlsx (fallback покрывает ошибку, но не молчаливую порчу формата). См. комментарий в issue #82.
## Проблема
OnlyOffice конвертирует `.xls/.doc/.ppt` → `.xlsx/.docx/.pptx` при загрузке. `UploadToFolderReplacing` матчил по точному `stem|ext` (`FindFilesByDedupKey`), поэтому повторный `oo dav upload FOLDER f.xls --replace` не находил сохранённый `f.xlsx` и создавал **второй файл** (live: id 3799+3887, 3800+3888 в `Banks/Caixa/extractos/`).
## Что сделано
- `EquivalentUploadExt` / `FindFilesByStemExt`: матч по stem с учётом серверной конвертации (legacy ↔ OOXML: `.xls/.doc/.ppt` ↔ `.xlsx/.docx/.pptx`).
- `planUploadReplacement`: выбирает выживающий файл и лишние дубликаты для замены.
- `UploadToFolderReplacing`: при совпадении **обновляет существующий файл по id** (`UpdateFile`, id стабилен, нет окна удаления), удаляет лишние дубликаты; при отказе портала — fallback на conversion-aware delete + upload (один файл на stem в любом случае).
- `AssertNoFileConflict` (`--no-replace`) использует тот же матчинг: `.xls` конфликтует с существующим `.xlsx`.
- `DeleteFilesByStemExt` — conversion-aware удаление.
- Документация: AGENTS.md, README, help `oo dav upload` / `oo projects files upload`.
## Тесты
- `files_replace_test.go` (offline, pure): `EquivalentUploadExt`, `FindFilesByStemExt`, `planUploadReplacement` (fresh / update / collapse duplicates), регрессия повторного `.xls`.
- `go test -race ./...`, `go vet ./...`, `gofmt -l` — чисто.
- PDF/XLSX-пути без изменений (exact-ext матч сохранён).
## Открытый вопрос
В process env нет `ONLYOFFICE_*` — live-проверка на реальном портале не выполнена (offline-тесты зелёные). Требует проверки: конвертирует ли `PUT /files/{id}/update` payload `.xls` в `.xlsx` (fallback покрывает ошибку, но не молчаливую порчу формата). См. комментарий в issue #82.
OnlyOffice converts legacy binary Office uploads (.xls/.doc/.ppt) into
OOXML (.xlsx/.docx/.pptx) on the server. UploadToFolderReplacing matched
by the exact stem|ext via FindFilesByDedupKey, so a repeated
`oo dav upload FOLDER f.xls --replace` never found the stored f.xlsx and
appended a second file (live: ids 3799+3887, 3800+3888).
- EquivalentUploadExt / FindFilesByStemExt: match by stem with a
legacy↔OOXML extension equivalence, so .xls finds the saved .xlsx.
- planUploadReplacement: pick the surviving file and the redundant
duplicate ids for a replacing upload.
- UploadToFolderReplacing updates the existing file in place (UpdateFile,
stable id, no delete window), removes extra duplicates, and falls back
to conversion-aware delete + upload when the portal rejects the update.
- AssertNoFileConflict (--no-replace) uses the same conversion-aware
matching so a .xls upload conflicts with an existing .xlsx.
- Offline tests cover the matcher, the plan and the repeated-.xls
regression; pdf/xlsx behaviour unchanged.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Проблема
OnlyOffice конвертирует
.xls/.doc/.ppt→.xlsx/.docx/.pptxпри загрузке.UploadToFolderReplacingматчил по точномуstem|ext(FindFilesByDedupKey), поэтому повторныйoo dav upload FOLDER f.xls --replaceне находил сохранённыйf.xlsxи создавал второй файл (live: id 3799+3887, 3800+3888 вBanks/Caixa/extractos/).Что сделано
EquivalentUploadExt/FindFilesByStemExt: матч по stem с учётом серверной конвертации (legacy ↔ OOXML:.xls/.doc/.ppt↔.xlsx/.docx/.pptx).planUploadReplacement: выбирает выживающий файл и лишние дубликаты для замены.UploadToFolderReplacing: при совпадении обновляет существующий файл по id (UpdateFile, id стабилен, нет окна удаления), удаляет лишние дубликаты; при отказе портала — fallback на conversion-aware delete + upload (один файл на stem в любом случае).AssertNoFileConflict(--no-replace) использует тот же матчинг:.xlsконфликтует с существующим.xlsx.DeleteFilesByStemExt— conversion-aware удаление.oo dav upload/oo projects files upload.Тесты
files_replace_test.go(offline, pure):EquivalentUploadExt,FindFilesByStemExt,planUploadReplacement(fresh / update / collapse duplicates), регрессия повторного.xls.go test -race ./...,go vet ./...,gofmt -l— чисто.Открытый вопрос
В process env нет
ONLYOFFICE_*— live-проверка на реальном портале не выполнена (offline-тесты зелёные). Требует проверки: конвертирует лиPUT /files/{id}/updatepayload.xlsв.xlsx(fallback покрывает ошибку, но не молчаливую порчу формата). См. комментарий в issue #82.