一次图片下载功能在 Windows 测试正常,部署到 Linux 后,返回的图片却损坏了。排查时,曾尝试把输入转成 URL、再转 URI 和文件对象;后来又发现数据库路径与配置前缀的拼接处出现了双斜杠。
这个经历留下了有价值的线索:必须检查实际读取的目标。但“Linux 不支持 FileInputStream”或“路径中间有双斜杠就一定读错”,都不是可靠结论。
先确认输入是路径还是地址
本地文件路径、file URI 和 HTTP URL 属于不同的命名空间。只有输入本来就是合法的 file URI 时,才适合按对应 URI 构造本地路径;HTTP URL 应通过网络客户端读取,不能直接当成本地文件。
对于明确的本地目录和文件名,可以用 Path 拼接,而不是手工不断添加斜杠:
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Path image = Paths.get("/srv/app/images").resolve("sample.png");
try (InputStream input = Files.newInputStream(image)) {
byte[] buffer = new byte[8192];
int count;
while ((count = input.read(buffer)) != -1) {
// 只处理 buffer 中前 count 个字节
}
}
这里的目录是示例,不是自动探测出的生产路径。文件名也不是直接接收任意用户输入;真实下载接口应按业务标识查找允许访问的文件,并另外处理路径越界、符号链接和权限问题。
重复斜杠不是充分证据
POSIX 对路径分隔符有明确规则:路径中间的连续斜杠一般等同于一个分隔符;恰好两个前导斜杠可能有实现相关含义,不能把这两种位置混为一谈。POSIX 路径解析
因此,即使修改路径后现象消失,也还应核对:原来读到哪个文件、是否存在编码差异、大小写是否正确、进程权限和挂载是否相同。不要把完整用户路径或敏感业务目录直接打印到公开日志。
把读取和响应分开验证
图片不能打开,也可能是读取之后的传输问题。可按以下顺序定位:
- 检查目标是否是预期普通文件,文件长度、图片格式与文件头是否合理。
- 对一个无敏感内容的小样本,比较源文件与下载响应保存后的长度和校验和。
- 检查 HTTP 状态和 Content-Type,确认返回的不是登录页、错误 JSON 或 HTML。
- 检查是否把二进制数据经过 Reader/Writer、是否写入了整个缓冲区而非实际 count,以及是否在中途截断响应。
不要先把流转成字符串再输出图片。对二进制响应使用字节流,明确响应由哪一层写入;文件能打开、HTTP 返回 200 和图片内容正确,是三个不同的检查点。