-
hanyul released this
2026-11-04 02:08:23 +09:00 다운로드는 끊기지 않는 방식 하나로
- 폴더나 여러 항목을 받을 때 더 이상 방식을 고르지 않습니다. Cloudflare가 연결을 끊거나 멈춰도 알아서 이어받는 방식으로 바로 받습니다.
- Chrome·Edge: 고른 폴더에 폴더 구조 그대로 저장합니다.
- Firefox: 이어받는 ZIP으로 받습니다. 다 받을 때까지 페이지를 열어 두세요.
- Safari·iOS: 이어받는 방식을 지원하지 않아 일반 ZIP으로 받습니다.
- 공유 페이지에는 전체 다운로드 버튼 하나만 남겼습니다. 'ZIP 다운로드' 버튼과 ZIP 안내 창은 없앴고, 목록의 하위 폴더 다운로드도 같은 방식으로 받습니다.
- 앱에서 폴더를 받을 때 뜨던 'ZIP / 폴더로 저장' 선택 창도 없앴습니다.
공유 링크
- 링크 설정에서 만료 기간을 바꿀 수 있습니다. 그대로 두거나, 지금부터 1일·7일·30일·90일·무제한, 또는 날짜를 지정할 수 있습니다.
- 공유 링크 기록에서 IP 주소를 끝까지 보여 줍니다. 긴 IPv6 주소는 콜론 뒤에서 줄을 바꿉니다.
- 휴대폰으로 연 공유 페이지 상단에 사이트 이름이 보입니다.
실수 방지
- 삭제 확인 창이 실제 동작을 알려 줍니다. 공유 폴더에 휴지통(
#recycle)이 있으면 휴지통으로 옮긴다고 안내하고, 없을 때만 되돌릴 수 없다고 알립니다. - 삭제처럼 위험한 확인 창은 처음에 취소가 선택돼 있어서, Enter를 눌러도 지워지지 않습니다.
- 옮기거나 복사할 때 같은 이름이 있으면 기본 선택이 '덮어쓰기'에서 둘 다 유지로 바뀌었습니다.
휴대폰과 보기 편의
- 휴대폰에서 여러 항목을 선택하면 아래 막대의 버튼이 3열로 줄을 바꿔 모두 보입니다. 선택하는 동안에는 앱 설치 안내를 숨깁니다.
- 터치 화면에서 체크박스와 작은 버튼을 키웠고, 조회 수 같은 링크와 정렬 버튼은 누르는 영역을 넓혔습니다.
- 다크 모드의 파란·빨간 버튼, 검색창 안내 글씨, 배지 글씨를 더 잘 읽히게 했습니다.
- 링크와 검색 지우기 버튼에 키보드 포커스 표시를 넣었고, 🔒 이모지를 다른 아이콘과 같은 선 아이콘으로 바꿨습니다.
- 확인 창의 문장이 단어 중간에서 끊기지 않습니다.
업데이트
compose.yaml은 바뀌지 않았습니다.docker compose pull && docker compose up -d하세요.이미지:
git.2ex.dev/hanyul/webdav:latestDownloads 2
-
Source code (zip)
0
2026-11-04 02:08:23 +09:00 -
Source code (tar.gz)
0
2026-11-04 02:08:23 +09:00
- 폴더나 여러 항목을 받을 때 더 이상 방식을 고르지 않습니다. Cloudflare가 연결을 끊거나 멈춰도 알아서 이어받는 방식으로 바로 받습니다.
-
hanyul released this
2026-10-31 15:31:47 +09:00 내 공유 링크 창
- 창을 넓혔습니다(너비 520px → 860px, 목록 높이 420px → 560px).
- 공유한 경로를
...로 자르지 않고 줄을 바꿔 끝까지 보여 줍니다. - 만료·생성 시각을
2026. 11. 07. 12:01 까지,2026. 10. 31. 12:01 생성처럼 띄어 쓰고, 항목 사이의·를 없앴습니다. 줄마다 날짜 위치가 맞습니다. - 날짜, 조회·다운로드 수, 배지가 중간에 끊기지 않습니다.
- 좁은 화면(640px 이하)에서는 버튼이 아래 줄로 내려가 경로와 날짜가 전체 폭을 씁니다.
업데이트
compose.yaml의 포트가 Web Station 포털에 맞춰127.0.0.1:30005로 바뀌었습니다.compose.yaml을 바꾼 뒤docker compose pull && docker compose up -d하세요.이미지:
git.2ex.dev/hanyul/webdav:latestDownloads 2
-
Source code (zip)
0
2026-10-31 15:31:47 +09:00 -
Source code (tar.gz)
0
2026-10-31 15:31:47 +09:00
-
hanyul released this
2026-10-29 10:12:15 +09:00 코드 정리
기능과 화면은 그대로이고, 내부 코드만 정리했습니다.
- 웹 화면의 여러 파일에 복사돼 있던 공통 함수(크기·날짜 표시, 아이콘, 텍스트 디코딩 등)를
public/util.js하나로 모았습니다. - 새 폴더·이름 바꾸기 입력 창, 파일과 ZIP의 이어받기(Range) 처리, ZIP 파일 읽기를 각각 하나로 합쳤습니다.
- 더 이상 필요 없는 코드를 지웠습니다: Node 26에서는 쓰이지 않는 CRC32 대체 구현, 1.1.0에서 이미 끝난 ZIP CRC 캐시 이전 코드, 화면에서 쓰지 않는 응답 필드, 겹치는 검사.
업데이트
compose.yaml은 바뀌지 않았습니다.docker compose pull && docker compose up -d하세요.이미지:
git.2ex.dev/hanyul/webdav:latestDownloads 2
-
Source code (zip)
0
2026-10-29 10:12:15 +09:00 -
Source code (tar.gz)
0
2026-10-29 10:12:15 +09:00
- 웹 화면의 여러 파일에 복사돼 있던 공통 함수(크기·날짜 표시, 아이콘, 텍스트 디코딩 등)를
-
hanyul released this
2026-10-28 21:17:24 +09:00 데이터 보호
- 공유 폴더 자체(맨 위 단계의 폴더)는 웹·WebDAV 어디서든 지우기, 옮기기, 이름 바꾸기를 할 수 없습니다. 맨 위 단계에는 파일이나 폴더를 만들 수 없습니다. 화면에서도 해당 버튼이 꺼집니다.
- 덮어쓴 기존 파일은
#recycle로 옮겨 둡니다. 중간에 실패하면 원래 파일을 되돌립니다. - 공유 폴더 사이 이동은 파일마다 복사한 뒤 원본을 지웁니다. 숨김 파일과 링크도 함께 옮기고, 그 안을 가리키던 공유 링크 경로가 따라갑니다.
- 복사할 때 링크는 따라가지 않고 링크 그대로 복사합니다.
새 기능
- 복사·이동 작업에 취소 버튼이 생겼습니다. 이미 옮긴 항목은 그대로 둡니다.
- 격자 보기: 시놀로지가 만들어 둔 썸네일을 보여 주고, 작은 이미지는 원본을 씁니다. 고른 보기는 기억합니다.
- 공유 링크
- 다운로드 횟수 제한
- 일시 중지(설정 버튼)
- 폴더 링크에서 방문자 업로드 허용: 이름이 겹치면
이름 (1)로 저장, 올린 파일 기록 탭
보안
- IP별 제한에 더해 계정별 로그인 실패 제한(
MAX_ACCOUNT_FAILURES, 기본 30)을 둡니다. WebDAV 로그인과 OTP 실패도 횟수에 넣습니다. - 패스키는 PIN이나 생체 인증을 요구합니다(
PASSKEY_REQUIRE_UV, 기본true). 사용 횟수를 확인하고, 등록되지 않은 계정에도 가짜 키 정보를 돌려줘서 계정 유무를 알 수 없게 합니다. - 로그인 세션을 해시로
state/app.db에 저장해서 재시작해도 로그인이 유지됩니다. 업데이트 직후에는 한 번 다시 로그인해야 합니다. - 활동 로그(
state/activity.log)에 로그인, 공유, 업로드, 이동·복사, WebDAV 쓰기를 남깁니다. - 보내는 파일에
Content-Security-Policy: sandbox(PDF 제외), 컨테이너는 읽기 전용(read_only,tmpfs /tmp,pids_limit)으로 바꿨습니다. - 공유 링크 방문자는 미디어 재생과 ZIP 받기를 동시에 몇 개까지만 할 수 있습니다. 공유 폴더 밖을 가리키는 링크는 목록에서 숨깁니다.
- Cloudflare IP 목록을
CLOUDFLARE_IPS로 바꿀 수 있습니다.
정리
- 웹 화면 코드를 기능별 모듈로 나눴고, 정적 파일은 ETag로 캐시합니다.
- ZIP 이어받기 계획을 다시 쓰고, CRC 캐시는 SQLite로 옮겼습니다.
- 단위 테스트(
npm run test:unit)를 추가했습니다.
업데이트
compose.yaml이 바뀌었습니다(읽기 전용 설정). 새compose.yaml을 받은 뒤docker compose pull && docker compose up -d하세요.이미지:
git.2ex.dev/hanyul/webdav:latestDownloads 2
-
Source code (zip)
0
2026-10-28 21:17:24 +09:00 -
Source code (tar.gz)
0
2026-10-28 21:17:24 +09:00
-
hanyul released this
2026-10-28 08:36:51 +09:00 공유 페이지 다운로드 버튼 정리
- 폴더를 열면 파란 전체 다운로드와 그 옆에 회색 ZIP 다운로드가 나옵니다.
- 전체 다운로드는 끊기거나 멈춰도 알아서 이어받습니다.
- Chrome·Edge: 고른 폴더에 폴더 구조 그대로 저장 (기존 '폴더째 받기')
- Firefox 등 (새로 추가): 페이지가 ZIP을 직접 받아 브라우저 다운로드로 넘깁니다. 연결이 끊기거나 30초 멈추면 끊긴 지점부터 다시 이어서, 브라우저에는 한 번도 끊기지 않은 다운로드로 보입니다. 다 받을 때까지 페이지를 열어 둬야 합니다.
- ZIP 다운로드는 브라우저가 직접 받는 ZIP으로, 누르면 끊길 수 있다는 안내가 먼저 나옵니다.
- 로그인 화면에서 폴더를 받을 때도 Firefox는 자동 이어받는 ZIP을 씁니다.
- Safari는 이 방식을 지원하지 않아 기존 ZIP 다운로드를 그대로 씁니다.
이미지:
git.2ex.dev/hanyul/webdav:1.0.4Downloads 2
-
Source code (zip)
0
2026-10-28 08:36:51 +09:00 -
Source code (tar.gz)
0
2026-10-28 08:36:51 +09:00
-
hanyul released this
2026-10-27 22:35:12 +09:00 만료된 공유 링크를 기록까지 바로 지우도록 바꾼 patch 릴리스입니다. 설정 변경은 필요 없습니다.
변경
- 만료되면 바로 삭제: 공유 링크가 만료되면 링크와 조회·다운로드 기록(
state/share-logs/<token>.jsonl)을 함께 삭제합니다. 이전에는 만료 뒤 7일 동안 "만료됨"으로 목록에 남았습니다. - 정리 주기: 1분마다 정리합니다(이전 1시간). 공유 목록을 열 때도 먼저 정리해서, 만료된 링크는 목록에 보이지 않습니다.
- 화면 정리: 공유 목록의 "만료됨" 표시와 관련 스타일을 없앴습니다.
검증
- E2E 테스트 35건 통과.
- 만료된 링크가 목록에서 사라지고, 기록 조회가 404를 돌려주는지 확인하는 검사를 추가했습니다.
- 배포 시점에 운영 서버에는 만료된 링크가 없었습니다(전체 5개).
이미지
git.2ex.dev/hanyul/webdav:1.0.3/latest:sha256:edf92de7f5e46e20bc96847c93d9e6cae0d2d85e4101d44ef84a25a15bcb9135릴리스 소스:
84db4d5622e4eaa513fa9eb7232897285a23bca7Downloads 2
-
Source code (zip)
0
2026-10-27 22:35:12 +09:00 -
Source code (tar.gz)
0
2026-10-27 22:35:12 +09:00
- 만료되면 바로 삭제: 공유 링크가 만료되면 링크와 조회·다운로드 기록(
-
hanyul released this
2026-10-27 22:29:07 +09:00 공유 페이지의 ZIP 다운로드에 끊김 경고를 추가한 patch 릴리스입니다. 설정 변경은 필요 없습니다.
변경
- ZIP 경고 창: 공유 페이지에서 "전체 다운로드 (ZIP)"를 누르면 먼저 경고 창을 띄웁니다. ZIP은 한 파일로 오래 받아서 Cloudflare 경유 중 끊기거나 멈출 수 있고, 그때는 브라우저 다운로드 목록에서 "다시 시작"을 눌러야 한다는 내용입니다.
- 폴더째 받기로 전환: Chrome·Edge에서는 경고 창에서 끊겨도 알아서 이어받는 "폴더째 받기"로 바로 바꿀 수 있고, 이 버튼이 기본 선택입니다. 폴더 저장을 지원하지 않는 브라우저(Firefox·Safari 등)에서는 취소와 "ZIP으로 받기"만 보입니다.
- 본 앱 다운로드 창: 같은 경고를 넣고, 폴더 저장 설명을 현재 동작("끊기거나 멈춰도 알아서 이어받음")에 맞췄습니다.
배경
1.0.1로 94GB를 다시 받아 본 결과입니다.
방식 끊김 직접 "다시 시작" 폴더째 받기 4번 0번 (모두 자동 복구) Chrome 기본 ZIP 다운로드 5번 5번 (Chrome이 스스로 재시도하지 않음) 두 방식 모두 파일은 정상이었습니다(크기 일치, ZIP CRC 전부 정상).
검증
브라우저 테스트로 Chromium과 폴더 API가 없는 브라우저를 각각 확인했습니다.
- 경고 문구와 버튼 구성
- 취소하면 다운로드하지 않음
- "ZIP으로 받기"는 다운로드 시작, "폴더째 받기"는 폴더 저장 완료
이미지
git.2ex.dev/hanyul/webdav:1.0.2/latest:sha256:b03ff043063d533928d8015b541459da8036f4fa5943f59a9dafd8df677d4322릴리스 소스:
1eb9203309e07223da1210775556d51505775da0Downloads 2
-
Source code (zip)
0
2026-10-27 22:29:07 +09:00 -
Source code (tar.gz)
0
2026-10-27 22:29:07 +09:00
-
hanyul released this
2026-10-27 17:05:23 +09:00 대용량 다운로드가 Cloudflare 경유 중 끊길 때 자동으로 복구하도록 고친 patch 릴리스입니다. 설정 변경은 필요 없습니다.
배경
94GB 공유 폴더를 실제로 받아 보며 끊김을 기록했습니다. 한 연결이 1~6분마다 끊겼고, 원인은 모두 Cloudflare 경로였습니다.
- 끊김 증상: TCP 리셋, Cloudflare의 HTTP/2 스트림 리셋(
INTERNAL_ERROR), TLS 레코드 손상(bad record mac). - 가장 나쁜 경우: 서버 쪽 요청만 끊고 받는 쪽 연결은 데이터 없이 열어 둡니다. 브라우저 다운로드가 0B/s로 멈춰 직접 "다시 시작"을 눌러야 합니다.
- 같은 회선에서도 연결마다 Cloudflare 데이터센터가 바뀝니다(HKG·NRT·LAX·PDX·SEA). 속도도 1~60MB/s로 크게 다릅니다.
- NAS 안에서는 끊김이 없었습니다: Node에 직접, DSM nginx(HTTP/2)를 거쳐 각각 450초씩 받았습니다.
변경
- 공유 페이지: Chrome·Edge에서는 "폴더째 받기"가 기본 버튼입니다. 끊기거나 멈추면 알아서 이어받습니다. ZIP은 보조 버튼입니다.
- 폴더째 받기: 30초 동안 데이터가 없으면 멈춘 연결로 보고 다시 연결합니다(이전 60초). 진행 없이 연속 10회까지 재시도합니다(이전 6회).
- 로그: 중간에 끊긴 응답을 보낸 양과 함께 기록합니다. (1.0.0 이후 반영)
검증
- ZIP 실다운로드: 94GB를 받는 동안 10번 끊겼고, 매번 끊긴 지점부터 이어받아 완료했습니다. 53개 파일 CRC 전부 정상.
- 브라우저 테스트: 한 파일에서 9번 끊어도 이어서 완료했습니다. 응답 없이 멈춘 요청은 31초 만에 다시 연결했습니다.
이미지
git.2ex.dev/hanyul/webdav:1.0.1/latest:sha256:a19e3ab8ca377886948381fb36a61b5f7f2f0fb57c6d665bf525f267e744f30d릴리스 소스:
60f3e7238a4e5aeda57b65bfce1fd5b64a732e1bDownloads 2
-
Source code (zip)
0
2026-10-27 17:05:23 +09:00 -
Source code (tar.gz)
0
2026-10-27 17:05:23 +09:00
- 끊김 증상: TCP 리셋, Cloudflare의 HTTP/2 스트림 리셋(
-
hanyul released this
2026-10-27 04:51:25 +09:00 Synology NAS용 브라우저·WebDAV 파일 서버의 첫 정식 릴리스입니다. DSM 계정과 패스키로 로그인하고, 브라우저와 Windows 탐색기(WebDAV)에서 같은 공유 폴더를 다룹니다.
주요 기능
- 로그인: DSM 계정(2단계 인증 포함)과 DSM에 등록한 패스키, 허용 사용자 제한, IP별 로그인 차단.
- 파일 관리: 탐색, 여러 개 선택(Shift·Ctrl+A), 끌어서 이동, 이름 변경·복사·삭제, 원격 검색.
- 업로드: 청크 업로드와 이어 올리기. Cloudflare 100MB 요청 제한 안에서 큰 파일도 올라갑니다.
- 다운로드
- 파일·폴더 ZIP 다운로드. 압축 결과가 항상 같아서 끊겨도 이어받을 수 있습니다.
- Chrome·Edge에서 "폴더째 받기": 파일 3개를 동시에 받고, 끊기면 파일 단위로 자동 이어받습니다.
- 미리보기
- 영상: 브라우저가 못 여는 코덱(HEVC 4:4:4, 10비트 H.264, Xvid, MPEG-TS 등)은 ffmpeg로 변환해 재생합니다.
- 자막: 같은 이름의 자막 파일과 내장 자막을 표시하고, 크기·배경·싱크를 설정할 수 있습니다. 음성 트랙도 고를 수 있습니다.
- 그 밖에 이미지, 음악, PDF, 텍스트를 미리 봅니다. 확장자를 모르는 파일도 텍스트로 열어 봅니다.
- 텍스트 편집: 원격 텍스트 파일을 바로 고쳐 저장합니다. 소유자와 권한은 유지하고, 그사이 다른 곳에서 바뀌었으면 알려 줍니다.
- 공유 링크: 만료일, 비밀번호, 조회·다운로드 기록, 디스코드 같은 메신저에서 보이는 링크 미리보기(OG 태그).
- WebDAV: URL 루트에서 Windows 탐색기 네트워크 위치로 연결됩니다.
- 모바일: 홈 화면에 추가(PWA) 안내.
이번 릴리스 직전 수정
- 재시작 뒤 ZIP 이어받기: 이어받을 지점 앞 파일들의 CRC를 백그라운드에서 계산하고, 결과를
state/zip-crc.json에 저장합니다. 88GB 지점에서 이어받아도 0.4초 안에 응답합니다. 이전에는 앞부분을 다 읽느라 Cloudflare 제한에 걸려 실패했습니다. - 폴더째 받기 재시도: 진행이 있으면 재시도 횟수를 초기화하고, 60초 동안 데이터가 없는 연결은 다시 연결합니다.
- 로그: 중간에 끊긴 응답도 보낸 양과 함께 기록합니다.
- 앱 설치 안내: 한 줄로 표시합니다.
이미지
태그 digest git.2ex.dev/hanyul/webdav:1.0.0/latestsha256:25959eadf54d333bc63edd0c9be16f27c8aa732213ffd699214a570bd42b0487linux/amd64, Node.js 26 (Alpine), ffmpeg 포함.compose.yaml은 이제 이 이미지를 받아 실행합니다. 업데이트는docker compose pull && docker compose up -d로 합니다. 특정 버전에 고정하려면.env에IMAGE_TAG=1.0.0을 적습니다.검증
- E2E 테스트 35건 통과: WebDAV, 업로드, 인증·패스키, ZIP 이어받기(CRC 캐시가 없는 상태 포함), 공유 링크, 영상 변환, 심볼릭 링크 차단, 클라이언트 IP 판별.
- 브라우저 테스트: 폴더째 받기에서 연결을 9번 끊어도 끝까지 받는지, 앱 설치 안내가 320·360·412px 화면에서 한 줄로 나오는지 확인.
- 운영 NAS에서 이 이미지로 전환해 정상 동작(healthy)과 실서비스 응답을 확인했습니다.
릴리스 소스:
a889e70404172f7978ca6d3670fe40ab34226922Downloads 2
-
Source code (zip)
0
2026-10-27 04:51:25 +09:00 -
Source code (tar.gz)
0
2026-10-27 04:51:25 +09:00