对象存储通过 bucket 和 key 定位文件。key 类似路径,但“目录”通常只是 key 的前缀;本地磁盘路径不是对象 URL。
上传并下载一个文件
下面使用 Java 21 与腾讯云 COS Java SDK,添加 Maven 依赖。完整 Maven 骨架可参考 Java HTML 解析文章,替换依赖即可:
<dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>5.6.281</version></dependency>准备最小权限的服务端凭据,通过环境设置 COS_SECRET_ID、COS_SECRET_KEY、COS_REGION、COS_BUCKET。region 如 ap-nanjing,bucket 使用控制台完整名称(包含 APPID 后缀)。不要把密钥放到前端或 Git。
保存 CosFileDemo.java:
import java.nio.file.Files;import java.nio.file.Path;import java.util.UUID;import com.qcloud.cos.COSClient;import com.qcloud.cos.ClientConfig;import com.qcloud.cos.auth.BasicCOSCredentials;import com.qcloud.cos.http.HttpProtocol;import com.qcloud.cos.region.Region;
public class CosFileDemo { private static String env(String name) { String value = System.getenv(name); if (value == null || value.isBlank()) throw new IllegalArgumentException("未设置 " + name); return value; } public static void main(String[] args) throws Exception { if (args.length != 1) throw new IllegalArgumentException("参数:本地文件路径"); Path source = Path.of(args[0]); if (!Files.isRegularFile(source)) throw new IllegalArgumentException("源文件不存在"); Path target = Path.of("cos-downloaded.bin"); if (Files.exists(target)) throw new IllegalArgumentException("下载目标已存在"); var config = new ClientConfig(new Region(env("COS_REGION"))); config.setHttpProtocol(HttpProtocol.https); config.setConnectionTimeout(5000); config.setSocketTimeout(15000); var client = new COSClient(new BasicCOSCredentials( env("COS_SECRET_ID"), env("COS_SECRET_KEY")), config); String bucket = env("COS_BUCKET"); String key = "tutorial/" + UUID.randomUUID(); try { client.putObject(bucket, key, source.toFile()); try (var object = client.getObject(bucket, key); var input = object.getObjectContent()) { Files.copy(input, target); } System.out.println("上传 key=" + key); System.out.println("内容一致=" + (Files.mismatch(source, target) == -1)); } finally { client.shutdown(); } }}mvn package dependency:copy-dependenciesjava -cp 'target/classes;target/dependency/*' CosFileDemo demo.pngLinux/macOS classpath 分隔符改为冒号。预期内容一致=true,在控制台能看到 tutorial 前缀下的对象。示例不自动删除它;核对后在控制台删除本次 key,避免误删其他内容。
怎样给浏览器访问
私有对象通过后端授权下载或短期签名 URL 提供给用户。SDK 下载成功不代表匿名 URL 可访问;公开读与公开写也不是同一个权限。浏览器直传使用范围和有效期受限的临时凭证或上传签名,不提供长期密钥。
下载 API 不接受客户端任意磁盘路径,也不能直接用未校验的 fileName 拼本地路径。Content-Disposition 文件名需要正确编码,返回内容类型与实际文件一致。
批量与生命周期
SDK 列举对象需要分页,删除前缀前先列出准确范围。部分删除失败要逐项处理;开启版本控制后删除标记不等于清除所有历史版本。
TransferManager 有线程池与客户端生命周期,线程池有界、任务有超时,退出时关闭。不要复制一段创建 32 个线程却没有关闭的工具类,并把它当完整服务。
评论