存储文件到 AW3 S3
添加依赖
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.17.100</version> <!-- 请检查并使用最新版本 -->
</dependency>
添加配置
AWS_S3_ACCESS_KEY_ID=
AWS_S3_SECRET_ACCESS_KEY=
AWS_S3_REGION_NAME=us-west-1
AWS_S3_BUCKET_NAME=rumiapp
AwsS3Utils 文件上传工具类
package com.litongjava.open.chat.utils;
import com.litongjava.tio.utils.environment.EnvUtils;
import com.litongjava.tio.utils.http.ContentTypeUtils;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class AwsS3Utils {
public static final String urlFormat = "https://%s.s3.us-west-1.amazonaws.com/%s";
public static final String bucketName = EnvUtils.get("AWS_S3_BUCKET_NAME");
public static final String regionName = EnvUtils.get("AWS_S3_REGION_NAME");
public static PutObjectResponse upload(S3Client client, String bucketName, String targetName, byte[] fileContent, String suffix) {
try {
String contentType = ContentTypeUtils.getContentType(suffix);
PutObjectRequest putOb = PutObjectRequest.builder().bucket(bucketName).key(targetName).contentType(contentType).build();
PutObjectResponse putObject = client.putObject(putOb, RequestBody.fromBytes(fileContent));
return putObject;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String getUrl(String targetName) {
return String.format(AwsS3Utils.urlFormat, AwsS3Utils.bucketName, targetName);
}
}
配置类
package com.litongjava.tio.boot.admin.config;
import com.litongjava.tio.utils.environment.EnvUtils;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3ClientBuilder;
public class AwsS3Config {
public S3Client buildClient() {
String accessKeyId = EnvUtils.get("AWS_S3_ACCESS_KEY_ID");
String secretAccessKey = EnvUtils.get("AWS_S3_SECRET_ACCESS_KEY");
String regionName = EnvUtils.get("AWS_S3_REGION_NAME");
AwsBasicCredentials awsCreds = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
StaticCredentialsProvider staticCredentialsProvider = StaticCredentialsProvider.create(awsCreds);
Region region = Region.of(regionName);
// 创建S3客户端
S3ClientBuilder builder = S3Client.builder();
S3Client s3 = builder.region(region) //
.credentialsProvider(staticCredentialsProvider) //
.build();
return s3;
}
}
测试工具类
package com.litongjava.tio.boot.admin.utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.Test;
import com.litongjava.tio.boot.admin.config.AwsS3Config;
import com.litongjava.tio.utils.environment.EnvUtils;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class AwsS3UtilsTest {
@Test
public void test() throws IOException {
EnvUtils.load();
Path path = java.nio.file.Paths.get("F:\\my_file\\my_photo\\kitty\\kitty-cat.jpg");
byte[] fileContent = Files.readAllBytes(path);
String targetName = "001.jpg"; // 上传到S3的文件名
String suffix = "jpg";
// 示例使用upload方法
try (S3Client client = new AwsS3Config().buildClient();) {
PutObjectResponse response = AwsS3Utils.upload(client, AwsS3Utils.bucketName, targetName, fileContent, suffix);
String url = String.format(AwsS3Utils.urlFormat, AwsS3Utils.bucketName, targetName);
System.out.println(url);
System.out.println(response.eTag());
}
}
}
接受文件上传,并经相关信息保存到数据库
package com.litongjava.tio.boot.admin.services;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.litongjava.db.TableInput;
import com.litongjava.db.TableResult;
import com.litongjava.db.activerecord.Record;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.table.services.ApiTable;
import com.litongjava.tio.boot.admin.costants.TioBootAdminTableNames;
import com.litongjava.tio.boot.admin.dao.SystemUploadFileDao;
import com.litongjava.tio.boot.admin.utils.AwsS3Utils;
import com.litongjava.tio.boot.admin.vo.UploadResultVo;
import com.litongjava.tio.http.common.UploadFile;
import com.litongjava.tio.utils.crypto.Md5Utils;
import com.litongjava.tio.utils.hutool.FilenameUtils;
import com.litongjava.tio.utils.snowflake.SnowflakeIdUtils;
import lombok.extern.slf4j.Slf4j;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
@Slf4j
public class AwsS3StorageService implements StorageService {
public RespBodyVo upload(String category, UploadFile uploadFile) {
if (StrKit.isBlank(category)) {
category = "default";
}
String filename = uploadFile.getName();
int size = uploadFile.getSize();
byte[] fileContent = uploadFile.getData();
return RespBodyVo.ok(uploadBytes(category, filename, size, fileContent));
}
public UploadResultVo uploadBytes(String category, String originFilename, int size, byte[] fileContent) {
// 上传文件
long id = SnowflakeIdUtils.id();
String suffix = FilenameUtils.getSuffix(originFilename);
String newFilename = id + "." + suffix;
String targetName = category + "/" + newFilename;
return uploadBytes(id, originFilename, targetName, fileContent, size, suffix);
}
/**
* @param id
* @param originFilename
* @param targetName
* @param fileContent
* @param size
* @param suffix
* @return
*/
public UploadResultVo uploadBytes(long id, String originFilename, String targetName, byte[] fileContent, int size, String suffix) {
String md5 = Md5Utils.digestHex(fileContent);
Record record = Aop.get(SystemUploadFileDao.class).getFileBasicInfoByMd5(md5);
if (record != null) {
log.info("select table reuslt:{}", record.toMap());
id = record.getLong("id");
String url = this.getUrl(record.getStr("bucket_name"), record.getStr("target_name"));
Kv kv = record.toKv();
kv.remove("target_name");
kv.remove("bucket_name");
kv.set("url", url);
kv.set("md5", md5);
return new UploadResultVo(id, originFilename, Long.valueOf(size), url, md5);
} else {
log.info("not found from cache table:{}", md5);
}
String etag = null;
try (S3Client client = AwsS3Utils.buildClient();) {
PutObjectResponse response = AwsS3Utils.upload(client, AwsS3Utils.bucketName, targetName, fileContent, suffix);
etag = response.eTag();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
// Log and save to database
log.info("Uploaded with ETag: {}", etag);
TableInput kv = TableInput.create().set("name", originFilename).set("size", size).set("md5", md5)
//
.set("platform", "aws s3").set("region_name", AwsS3Utils.regionName).set("bucket_name", AwsS3Utils.bucketName)
//
.set("target_name", targetName).set("file_id", etag);
TableResult<Kv> save = ApiTable.save(TioBootAdminTableNames.tio_boot_admin_system_upload_file, kv);
String downloadUrl = getUrl(AwsS3Utils.bucketName, targetName);
return new UploadResultVo(save.getData().getLong("id"), originFilename, Long.valueOf(size), downloadUrl, md5);
}
@Override
public String getUrl(String bucketName, String targetName) {
return Aop.get(SystemUploadFileService.class).getUrl(bucketName, targetName);
}
@Override
public UploadResultVo getUrlById(String id) {
return Aop.get(SystemUploadFileService.class).getUrlById(id);
}
@Override
public UploadResultVo getUrlById(long id) {
return Aop.get(SystemUploadFileService.class).getUrlById(id);
}
@Override
public UploadResultVo getUrlByMd5(String md5) {
return Aop.get(SystemUploadFileService.class).getUrlByMd5(md5);
}
}
添加 action 中接收上传文件
import java.util.Map;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.litongjava.db.TableInput;
import com.litongjava.db.TableResult;
import com.litongjava.db.activerecord.Record;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.open.chat.constants.TableNames;
import com.litongjava.open.chat.model.UploadResultVo;
import com.litongjava.open.chat.services.AwsS3StorageService;
import com.litongjava.table.services.ApiTable;
import com.litongjava.table.utils.TableInputUtils;
import com.litongjava.table.utils.TableResultUtils;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.boot.utils.TioRequestParamUtils;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.common.UploadFile;
import com.litongjava.tio.http.server.model.HttpCors;
import com.litongjava.tio.http.server.util.CORSUtils;
import com.litongjava.tio.http.server.util.Resps;
public class SystemFileS3Handler {
public HttpResponse upload(HttpRequest request) throws Exception {
HttpResponse httpResponse = TioRequestContext.getResponse();
CORSUtils.enableCORS(httpResponse, new HttpCors());
UploadFile uploadFile = request.getUploadFile("file");
String category = request.getParam("category");
AwsS3StorageService storageService = Aop.get(AwsS3StorageService.class);
if (uploadFile != null) {
RespBodyVo RespBodyVo = storageService.upload(category, uploadFile);
return Resps.json(httpResponse, RespBodyVo);
}
return Resps.json(httpResponse, RespBodyVo.ok("Fail"));
}
public HttpResponse getUploadRecordByMd5(HttpRequest request) throws Exception {
HttpResponse httpResponse = TioRequestContext.getResponse();
CORSUtils.enableCORS(httpResponse, new HttpCors());
Map<String, Object> map = TioRequestParamUtils.getRequestMap(request);
TableInput kv = TableInputUtils.camelToUnderscore(map);
// 调用ApiTable查询数据
TableResult<Record> jsonBean = ApiTable.get(TableNames.tio_boot_admin_system_upload_file, kv);
TableResult<Kv> TableResult = TableResultUtils.recordToKv(jsonBean);
return Resps.json(httpResponse, RespBodyVo.ok(TableResult.getData()).code(TableResult.getCode()).msg(TableResult.getMsg()));
}
public HttpResponse getUrl(HttpRequest request) throws Exception {
HttpResponse httpResponse = TioRequestContext.getResponse();
CORSUtils.enableCORS(httpResponse, new HttpCors());
AwsS3StorageService storageService = Aop.get(AwsS3StorageService.class);
RespBodyVo respBodyVo = null;
String id = request.getParam("id");
String md5 = request.getParam("md5");
if (StrKit.notBlank(id)) {
// id,md5,name,url,
UploadResultVo uploadResultVo = storageService.getUrlById(id);
if (uploadResultVo == null) {
respBodyVo = RespBodyVo.fail();
} else {
respBodyVo = RespBodyVo.ok(uploadResultVo);
}
} else if (StrKit.notBlank(md5)) {
UploadResultVo uploadResultVo = storageService.getUrlByMd5(md5);
if (uploadResultVo == null) {
respBodyVo = RespBodyVo.fail();
} else {
respBodyVo = RespBodyVo.ok(uploadResultVo);
}
} else {
respBodyVo = RespBodyVo.fail("id or md5 can not be empty");
}
return Resps.json(httpResponse, respBodyVo);
}
}
配置路由
SystemFileS3Handler systemFileS3Handler = Aop.get(SystemFileS3Handler.class);
r.add("/api/system/file/s3/upload", systemFileS3Handler::upload);
r.add("/api/system/file/s3/md5", systemFileS3Handler::getUploadRecordByMd5);
r.add("/api/system/file/s3/url", systemFileS3Handler::getUrl);
测试
测试上传
curl --location --request POST 'http://localhost:8100/tio-boot-admin/api/system/file/upload/s3' \
--header 'authorization: 123456' \
--header 'Content-Type: multipart/form-data; boundary=--------------------------946279255222128586808179' \
--header 'Cookie: PHPSESSID=f1aa9dbe6c8e4d06aa5bc59d3b7b43b2' \
--form 'file=@"F:\\my_file\\my_photo\\aliyun\\配置.png"' \
--form 'category="sjsu/professor"'
返回数据
{
"code": 1,
"data": {
"id": "394502029835268096",
"url": "https://rumiapp.s3.us-west-1.amazonaws.com/sjsu/professor/394502024734994432.png"
},
"ok": true
}