Вот зависимость, определенные в pom.xml
Код: Выделить всё
software.amazon.awssdk
s3
${cloudflare-aws-sdk-version}
compile
software.amazon.awssdk
apache-client
${cloudflare-aws-sdk-version}
org.apache.httpcomponents
httpclient
${apache-httpclient.version}
< /code>
Вот файл Application.yml, показанный ниже < /p>
cloudflare:
r2:
endpoint: https://.r2.cloudflarestorage.com
accessKey: access-key
secretKey: secret-key
bucket: buckey-name
< /code>
Вот класс CloudFlareProperties, показанный ниже < /p>
@Getter
@Setter
@ConfigurationProperties(prefix = "cloudflare.r2")
public class CloudflareProperties {
private String endpoint;
private String accessKey;
private String secretKey;
}
< /code>
Вот класс CloudFlarer2Config, показанный ниже < /p>
@Configuration
@EnableConfigurationProperties(CloudflareProperties.class)
@RequiredArgsConstructor
public class CloudflareR2Config {
private final CloudflareProperties cloudflareProperties;
@Bean
public S3Client s3Client() {
return S3Client.builder()
.httpClientBuilder(ApacheHttpClient.builder())
.region(Region.of("eeur"))
.endpointOverride(URI.create(cloudflareProperties.getEndpoint()))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(
cloudflareProperties.getAccessKey(),
cloudflareProperties.getSecretKey())))
.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build())
.build();
}
}
< /code>
Вот класс службы, показанный ниже < /p>
@Service
@RequiredArgsConstructor
public class MediaService {
private final S3Client s3Client;
@Value("${cloudflare.r2.bucket}")
private String bucket;
public String uploadFile(MultipartFile file) {
String originalFilename = Optional.ofNullable(file.getOriginalFilename())
.orElseThrow(() -> new UnsupportedMediaTypeException("Filename is missing"))
.toLowerCase();
String contentType = Optional.ofNullable(file.getContentType())
.orElseThrow(() -> new UnsupportedMediaTypeException("Content-Type is unknown"));
String folder = switch (getFileExtension(originalFilename)) {
case "jpg", "jpeg", "png" -> "images";
case "mp4", "mov" -> "videos";
default -> throw new UnsupportedMediaTypeException("Unsupported file type: " + contentType);
};
String key = folder + "/" + UUID.randomUUID() + "-" + originalFilename;
PutObjectRequest putRequest = PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType(contentType)
.build();
try {
s3Client.putObject(putRequest, RequestBody.fromBytes(file.getBytes()));
} catch (IOException e) {
throw new FileUploadException("File upload to Cloudflare R2 failed", e);
}
return key;
}
private String getFileExtension(String filename) {
int lastDot = filename.lastIndexOf('.');
if (lastDot == -1 || lastDot == filename.length() - 1) {
throw new IllegalArgumentException("Invalid file extension in filename: " + filename);
}
return filename.substring(lastDot + 1);
}
}
< /code>
Вот класс контроллера, показанный ниже < /p>
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/media")
public class MediaController {
private final MediaService mediaService;
@PostMapping("/upload")
public ResponseEntity uploadImage(@RequestParam("file") MultipartFile file) {
String key = mediaService.uploadFile(file);
return ResponseEntity.ok(key);
}
}
Код: Выделить всё
{
"error": "Internal Server Error",
"message": "Unauthorized (Service: S3, Status Code: 401, Request ID: null) (SDK Attempt Count: 1)"
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... storage-in