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上的文件名。
具体修改
更新
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); } }新增/修改
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
相关产品推荐
相关产品推荐

