3.2 KiB
Nextcloud File Upload Diagnostics
When files appear visible in the Nextcloud web UI but find on the container filesystem returns nothing, use this diagnostic sequence.
Step 1: Check physical filesystem
docker exec <container> find '<nc_data_path>/<dir>' -type f -exec ls -la {} \;
Look for .part and .ocTransferId* files — these are incomplete upload fragments.
Step 2: Rescan
docker exec -u www-data <container> php occ files:scan admin --path='<path>'
Step 3: Check Nextcloud logs
docker exec <container> tail -20 /var/www/html/data/nextcloud.log | python3 -c "
import sys, json
for line in sys.stdin:
try:
d = json.loads(line.strip())
if d.get('level', 0) >= 2:
print(f'[{d.get(\"time\",\"?\")}] {d.get(\"message\",\"\")[:300]}')
except: pass
"
Upload failures show: "预期文件大小为 X字节,实际...写入...Y字节"
Step 4: Query MariaDB directly
Find the DB password first:
docker exec <container> grep dbpassword /var/www/html/config/config.php
Then query (use mariadb client, not mysql):
docker exec nextcloud-db-1 mariadb -u nextcloud -p<DB_PASSWORD_FROM_CONFIG> nextcloud -e "
SELECT f.fileid, f.path, f.name, f.size, FROM_UNIXTIME(f.mtime) as modified
FROM oc_filecache f
WHERE f.path LIKE '%<search_term>%'
ORDER BY f.path;
"
To find children of a directory (by parent fileid):
... -e "SELECT f.fileid, f.parent, f.path, f.name, f.size
FROM oc_filecache f WHERE f.parent IN (<parent_id1>, <parent_id2>);"
Step 5: Clean up fragments
docker exec <container> find '<path>' -name '*.part' -delete
docker exec <container> find '<path>' -name '*.ocTransferId*' -delete
Common root cause
Cloudflare Tunnel (free tier) truncates large file uploads. The Nextcloud chunked upload protocol partially writes, then the connection drops. Repeated retries produce the same result.
Solution: Receive files via alternate channel (WeChat private message → ~/.hermes/cache/documents/) and docker cp into Nextcloud.
Quirk: docker cp'd file present + md5 correct, but files:scan returns 0 and DB row missing (2026-06-17)
After docker cp + chown www-data a new xlsx, php occ files:scan admin --path='小Maggie协作区/.../世茂' returned all-zeros (Folders 0 Files 0) and oc_filecache had no row for the file — so it was invisible in the web UI despite physically existing with a correct md5.
Root cause: files:scan keys off directory mtime; a fresh docker cp into an existing dir doesn't always bump the parent mtime, so the scanner skips it.
Fix (verified):
# 1. touch the parent dir to force an mtime change
docker exec <container> bash -c "touch '/var/www/html/data/admin/files/<REL_PATH>'"
# 2. rescan using the admin/files/ prefixed --path form (not the bare share path)
docker exec -u www-data <container> php occ files:scan --path="admin/files/<REL_PATH>"
This returns Updated N and registers the file. Always verify after upload by querying oc_filecache for the filename (Step 4) — md5 match alone does NOT prove the file is indexed/visible. Don't tell the user "uploaded" until the DB row exists.