You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无Maven依赖、不使用SDK的情况下用纯Java上传文件至Amazon S3

纯Java无依赖上传文本文件到Amazon S3

当然可以,直接调用Amazon S3的REST API就能实现,不需要任何外部依赖。核心是手动实现AWS的签名认证逻辑,然后构造HTTP PUT请求上传文本内容。

步骤说明

  • 提前准备好AWS访问密钥(Access Key ID + Secret Access Key)、S3存储桶名称、存储桶所在区域,以及要上传的文本内容和目标对象键(即文件在S3里的路径/名称)。
  • 核心是生成符合AWS v4签名规范的认证头,这一步用Java自带的javax.crypto和java.net包就能实现。

完整代码示例

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class S3TextUploader {
    private static final String AWS_ACCESS_KEY = "你的AWS Access Key ID";
    private static final String AWS_SECRET_KEY = "你的AWS Secret Access Key";
    private static final String BUCKET_NAME = "你的存储桶名称";
    private static final String REGION = "存储桶区域(比如us-east-1)";
    private static final String OBJECT_KEY = "目标对象键(比如test.txt)";
    private static final String TEXT_CONTENT = "要上传的文本内容";

    public static void main(String[] args) throws Exception {
        // 生成日期和时间戳(符合AWS要求的格式)
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        String currentDate = dateFormat.format(new Date());
        String dateStamp = currentDate.substring(0, 8);

        // 1. 构造待签名字符串
        String httpMethod = "PUT";
        String canonicalUri = "/" + OBJECT_KEY;
        String canonicalQueryString = "";
        String canonicalHeaders = "host:" + BUCKET_NAME + ".s3." + REGION + ".amazonaws.com\n" +
                "x-amz-content-sha256:" + sha256Hash(TEXT_CONTENT.getBytes(StandardCharsets.UTF_8)) + "\n" +
                "x-amz-date:" + currentDate + "\n";
        String signedHeaders = "host;x-amz-content-sha256;x-amz-date";
        String payloadHash = sha256Hash(TEXT_CONTENT.getBytes(StandardCharsets.UTF_8));

        String canonicalRequest = httpMethod + "\n" +
                canonicalUri + "\n" +
                canonicalQueryString + "\n" +
                canonicalHeaders + "\n" +
                signedHeaders + "\n" +
                payloadHash;

        // 2. 构造签名字符串
        String algorithm = "AWS4-HMAC-SHA256";
        String credentialScope = dateStamp + "/" + REGION + "/s3/aws4_request";
        String stringToSign = algorithm + "\n" +
                currentDate + "\n" +
                credentialScope + "\n" +
                sha256Hash(canonicalRequest.getBytes(StandardCharsets.UTF_8));

        // 3. 计算签名
        byte[] signingKey = getSigningKey(AWS_SECRET_KEY, dateStamp, REGION, "s3");
        String signature = bytesToHex(hmacSha256(signingKey, stringToSign.getBytes(StandardCharsets.UTF_8)));

        // 4. 构造Authorization头
        String authorizationHeader = algorithm + " " +
                "Credential=" + AWS_ACCESS_KEY + "/" + credentialScope + ", " +
                "SignedHeaders=" + signedHeaders + ", " +
                "Signature=" + signature;

        // 5. 发送PUT请求
        URL url = new URL("https://" + BUCKET_NAME + ".s3." + REGION + ".amazonaws.com/" + OBJECT_KEY);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("PUT");
        connection.setDoOutput(true);

        // 设置请求头
        connection.setRequestProperty("Host", BUCKET_NAME + ".s3." + REGION + ".amazonaws.com");
        connection.setRequestProperty("x-amz-date", currentDate);
        connection.setRequestProperty("x-amz-content-sha256", payloadHash);
        connection.setRequestProperty("Authorization", authorizationHeader);
        connection.setRequestProperty("Content-Type", "text/plain; charset=UTF-8");

        // 写入文本内容
        try (OutputStream os = connection.getOutputStream()) {
            os.write(TEXT_CONTENT.getBytes(StandardCharsets.UTF_8));
        }

        // 检查响应状态
        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
            System.out.println("文本上传成功!");
        } else {
            System.out.println("上传失败,响应码:" + responseCode);
            System.out.println("响应信息:" + connection.getResponseMessage());
        }
    }

    // 计算SHA256哈希并转为十六进制字符串
    private static String sha256Hash(byte[] input) throws Exception {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(input);
        return bytesToHex(digest);
    }

    // 计算HMAC-SHA256
    private static byte[] hmacSha256(byte[] key, byte[] data) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(key, "HmacSHA256"));
        return mac.doFinal(data);
    }

    // 生成AWS v4签名密钥
    private static byte[] getSigningKey(String secretKey, String dateStamp, String regionName, String serviceName) throws Exception {
        byte[] kSecret = ("AWS4" + secretKey).getBytes(StandardCharsets.UTF_8);
        byte[] kDate = hmacSha256(kSecret, dateStamp.getBytes(StandardCharsets.UTF_8));
        byte[] kRegion = hmacSha256(kDate, regionName.getBytes(StandardCharsets.UTF_8));
        byte[] kService = hmacSha256(kRegion, serviceName.getBytes(StandardCharsets.UTF_8));
        return hmacSha256(kService, "aws4_request".getBytes(StandardCharsets.UTF_8));
    }

    // 字节数组转十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

注意事项

  • 替换代码中的占位符(AWS密钥、存储桶信息、文本内容等)为你自己的实际数据。
  • 确保你的AWS密钥拥有S3的PutObject权限,避免权限不足导致上传失败。
  • 如果上传的文本内容较大,考虑分块上传,但对于常规文本文件,上述代码足够使用。
  • 日期和时间必须使用UTC时区,否则签名会验证失败。

内容的提问来源于stack exchange,提问作者KisnardOnline

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:05:30