Remote file access (3/4): downloadFile(remote, local) — the symmetric, digest-verified counterpart of uploadFile

Aperta
#147 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Tranquilla
Stack tecnologico
java

Direzione di ricerca

Inizia leggendo WinRMClient.uploadFile e la lettura a intervalli/in streaming dell’issue #146, quindi esamina ShellFileCopy.digestHex, parseAnyDigest, CERTUTIL_ALGORITHMS e le costanti per i retry dovuti alla quota. Usa i test di FakeWsmanServer per coprire round trip, mismatch dei digest, interruzioni e destinazioni identiche, e aggiungi il controllo live in WinRMLiveTest. Il lavoro è completato quando mvn verify site ha esito positivo, file-transfers.md e il README documentano le garanzie e la raccomandazione SMB e non rimane alcun file di destinazione parziale.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Third issue of the remote file access family: the missing symmetric half of WinRMClient.uploadFile(Path, String). Builds on the ranged/streaming read of #146.

Context

client.uploadFile(Path localFile, String remoteFile) has existed since the smbj removal (#117): it pushes a local file through the WinRM channel itself, digest-verified, skipping the transfer when the destination already has identical content. There is no way back. Every caller that needs to retrieve a remote log or a command's output file has to shell out to type/Get-Content and hope the encoding survives.

downloadFile is the mirror image, and it should mirror the upload's guarantees, not just its direction: verified integrity, no wasted transfer, and no half-written local file left behind on failure.

Proposed API

Symmetric with the existing method, on the client:

client.downloadFile("C:\\Windows\\Temp\\collect.log", Path.of("collect.log"));

And as a terminal on the per-path request, for the fluent form:

long bytes = client.file("C:\\Windows\\Temp\\collect.log")
    .downloadTo(Path.of("collect.log"));

Requirements

  • Digest verification, both ways. Compute the remote digest with the probe ShellFileCopy already has (certutil -hashfile, SHA256 with a SHA1 fallback — see CERTUTIL_ALGORITHMS), compare it with the digest of the received bytes, and fail with the same shape of WindowsRemoteException the upload path raises on a mismatch. Reuse ShellFileCopy.digestHex / parseAnyDigest rather than reimplementing.
  • Skip an identical transfer, matching the upload's behavior: if the local destination already exists with the same digest, do not transfer, and say so (return value or documented no-op).
  • Atomic destination: stream into a temporary file in the destination's directory, fsync, then ATOMIC_MOVE onto the target. A failure or a timeout must never leave a truncated file at the destination path.
  • Bounded memory: built on the streaming read, never readBytes() into a byte[] first. A 500 MB file must download in constant memory (slowly — see below).
  • Downloads are not resumable — decided, and deliberately out of scope: an interrupted download starts over. Resuming would mean tracking verified byte counts across attempts and re-validating that the remote file has not changed, which is more state machine than this transport's speed justifies. Say so in the Javadoc and in file-transfers.md so callers do not expect otherwise.
  • Reuse the quota-rejection retry (isRetryableQuotaRejection, QUOTA_RETRIES, QUOTA_RETRY_DELAY_MILLIS): a long download hits the same WinRM operation quotas the upload does.
  • Directory destination: downloadFile(remote, Path.of("C:\\dir")) where the local path is an existing directory should write dir\<remote file name> — or reject it. Pick one, document it.
  • Honest performance documentation. Base64 through a command shell is roughly an order of magnitude slower than SMB; publish a measured figure from the live host in file-transfers.md and keep the existing "not a bulk transport" caveat prominent. Callers moving gigabytes should use SMB, and the docs should say so.
  • Timeout is the client's wall-clock deadline for the blocking method; a large download will need an explicitly raised timeout, and the exception message must make the cause obvious (bytes transferred / total when it fired).

Tests & docs

  • Round-trip test: uploadFile then downloadFile returns byte-identical content, for a binary file with every byte value and for a file with a non-ASCII name.
  • FakeWsmanServer tests: digest mismatch → failure with no file at the destination; interruption mid-transfer → no partial file left behind and no half-written temporary file; identical-digest destination → no transfer performed.
  • WinRMLiveTest: download a real file from anaxagore and verify its digest.
  • file-transfers.md extended with the download direction, the integrity and atomicity guarantees, the measured throughput, and the SMB recommendation for bulk data; README snippet next to uploadFile.

Acceptance criteria

  • downloadFile retrieves byte-exact content, digest-verified against the remote host.
  • No partial file is ever visible at the destination path — verified by a test that interrupts mid-transfer.
  • An identical local file is not re-downloaded.
  • A file substantially larger than the JVM heap downloads successfully.
  • mvn verify site green: no checkstyle/PMD/SpotBugs findings, full Javadoc, docs updated.

🤖 Generated with Claude Code

Lingua principale
Java
Stelle
11
Fork
4
Merge medio
5g 5h
PR unite (30g)
6

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di MetricsHub/winrm-java

Tutte le issue di MetricsHub/winrm-java

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.