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

Java程序向AWS S3存文件时本地项目目录重复存储问题求助

问题描述

我开发了一个可将文件存储至Amazon S3的Java程序,功能正常,但文件不仅会存入S3存储桶,还会保存到本地项目目录。我推测问题源于创建指定路径的File实例File file = new File(timestamp + ".jpg");,想了解如何避免本地存储,同时仍能设置所需文件名?

相关代码

保存文件至存储的代码

public void saveFileToStorage(String url, Long timestamp, Integer deviceId) {
    S3Repository repository = new S3Repository(bucketName);
    File file = new File(timestamp + ".jpg");
    try {
        URL link = new URL(url);
        Thread.sleep(1500);//wait until URL is ready for download
        FileUtils.copyURLToFile(link, file);
        repository.uploadFile(timestamp.toString(), file, deviceId.toString()+"/");
    } catch (IOException | InterruptedException e) {
        log.error(e.getMessage() + " - check thread sleep time!");
        throw new RuntimeException(e);
    }
}

仓库中的上传方法

public void uploadFile(String keyName, File file, String folder) {
    ObjectMetadata metadata = new ObjectMetadata();
    metadata.setContentLength(0);
    s3client.putObject(bucketName, folder, new ByteArrayInputStream(new byte[0]), metadata);
    s3client.putObject(new PutObjectRequest(bucketName, folder+keyName, file));
}
解决方案

核心问题确实是FileUtils.copyURLToFile(link, file)这一步将文件下载到了本地。要避免本地存储,直接通过InputStream读取URL内容并上传至S3即可,无需生成本地文件,同时仍能完全控制S3上的文件名。

具体修改

  1. 更新saveFileToStorage方法
    移除本地File实例的创建,直接获取URL的输入流,传入修改后的上传方法:

    public void saveFileToStorage(String url, Long timestamp, Integer deviceId) {
        S3Repository repository = new S3Repository(bucketName);
        try {
            URL link = new URL(url);
            Thread.sleep(1500);// 等待URL可下载
            // 使用try-with-resources自动关闭输入流
            try (InputStream inputStream = link.openStream()) {
                // 传入文件名后缀,确保S3上的文件名为timestamp.jpg
                repository.uploadFile(timestamp.toString(), inputStream, deviceId.toString()+"/", ".jpg");
            }
        } catch (IOException | InterruptedException e) {
            log.error(e.getMessage() + " - 检查线程休眠时间!");
            throw new RuntimeException(e);
        }
    }
    
  2. 新增/修改uploadFile重载方法
    新增支持InputStream上传的版本,通过参数拼接S3上的完整文件名,同时保留原有的文件夹创建逻辑:

    public void uploadFile(String keyName, InputStream inputStream, String folder, String fileSuffix) {
        // 创建S3文件夹(如果需要)
        ObjectMetadata folderMetadata = new ObjectMetadata();
        folderMetadata.setContentLength(0);
        s3client.putObject(bucketName, folder, new ByteArrayInputStream(new byte[0]), folderMetadata);
        
        // 设置文件元数据,若能提前获取文件大小可设置ContentLength以优化上传
        ObjectMetadata fileMetadata = new ObjectMetadata();
        
        // 拼接S3上的完整键名:文件夹路径 + 文件名 + 后缀
        String fullS3Key = folder + keyName + fileSuffix;
        s3client.putObject(new PutObjectRequest(bucketName, fullS3Key, inputStream, fileMetadata));
    }
    

补充说明

  • 使用try-with-resources包裹InputStream,确保流自动关闭,避免资源泄漏。
  • 如果无法提前获取URL文件的大小,可以跳过setContentLength,AWS SDK会自动处理分块上传。
  • 此方案彻底消除了本地文件的创建和写入,同时通过fullS3Key完全控制S3存储桶中的文件名结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 10:50:15