Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

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

已关闭
#147 0 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
35/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
冷清
技术栈
java

调研方向

先阅读 WinRMClient.uploadFile 以及 issue #146 中的范围/流式读取,然后检查 ShellFileCopy.digestHex、parseAnyDigest、CERTUTIL_ALGORITHMS 和配额重试常量。使用 FakeWsmanServer 的测试覆盖往返、摘要不匹配、中断和相同目标,并在 WinRMLiveTest 中添加实时检查。完成标准是 mvn verify site 通过,file-transfers.md 和 README 记录这些保证以及 SMB 建议,并且不残留部分目标文件。

由索引模型根据 Issue 内容生成。

描述

Third issue of the remote file access family: the missing symmetric half of WinRMClient.uploadFile(Path, String). Builds on openStream() from #146 (the foundation) — it does not need the listing of #145.

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"));

Flow — one remote digest probe

  1. Probe the remote digest with ShellFileCopy.digestProbe / parseAnyDigest.
  2. If the local destination exists with the same digest → no transfer, return.
  3. Otherwise client.file(remote).openStream() → DigestInputStream → temporary file in the destination's directory.
  4. Compare the received digest with the probed one; on match fsync and ATOMIC_MOVE onto the target. On any failure (mismatch, timeout, interruption) delete the temporary file.

A file modified between the probe and the transfer shows up as a digest mismatch — the correct outcome.

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 writes dir\<remote file name>, like cp — decided (the CLI get default destination in #148 needs the same resolution). 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

主要语言
Java
星标
13
派生
4
平均合并
1 天 5 小时
30 天内合并 PR
18

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

MetricsHub/winrm-java 的其他 Issue

查看 MetricsHub/winrm-java 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。