我想使用SpringBoot RestTemplate进行调用,将一个文件上传到S3桶:PutObject.html
PUT /my-image.jpg HTTP/1.1
Host: myBucket.s3.<Region>.amazonaws.com
Date: Wed, 12 Oct 2009 17:50:00 GMT
Authorization: authorization string
Content-Type: text/plain
Content-Length: 11434
x-amz-meta-author: Janet
Expect: 100-continue
[11434 bytes of object data]和
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.rootUri("")
.additionalInterceptors((request, body, execution) -> {
request.getHeaders().add("Authorization",
"Bearer a0d78d7922f333ee22d75bea53d01hhkjk83f5ac03f11ccd87787");
return execution.execute(request, body);
}).build();
}我试过了
Resource resource = new ClassPathResource("logback.xml");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
HttpEntity<byte[]> requestEntity
= new HttpEntity<>(StreamUtils.copyToByteArray(resource.getInputStream()), headers);
Map<String, Object> parameters = new HashMap<>(4);
parameters.put("cors_enabled", true);
parameters.put("acl", "private");
parameters.put("key", "my-key");
parameters.put("Bucket", "parameters.put("Bucket", "https://cloud.linode.com/object-storage/buckets/eu-central-1/my-bucket-2020");");
restTemplate.put("https://api.linode.com/v4/object-storage/buckets", requestEntity, parameters);但我有
org.springframework.web.client.HttpClientErrorException$MethodNotAllowed: 405 METHOD NOT ALLOWED: [{"errors": [{"reason": "Method Not Allowed"}]}]另外,当我得到一个问题:
MultiValueMap<String, Object> body
= new LinkedMultiValueMap<>();
UriComponentsBuilder builder =
UriComponentsBuilder.fromHttpUrl("https://api.linode.com/v4/object-storage/buckets/eu-central-1/my-bucket-2020/object-url");
builder.queryParam("method", "GET");
builder.queryParam("name", "43f959d9-a11a-4f2cec88fd7e.JPG");
body.add("method", "GET");
body.add("name", "43f959d9-a11a-4f2cec88fd7e.JPG");
HttpHeaders headers = new HttpHeaders();
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
restTemplate.postForEntity(builder.build().encode().toUri(),
requestEntity, LinodeResponse.class);以及答复:
org.springframework.web.client.HttpClientErrorException$BadRequest: 400 BAD REQUEST: [{"errors": [{"reason": "name is required", "field": "name"}, {"reason": "method is required", "field": "method"}]}]使用AWS访问ans时,我有以下错误:
com.amazonaws.services.s3.model.AmazonS3Exception: The AWS Access Key Id you provided does not exist in our records. 发布于 2020-12-19 16:33:25
Linode似乎提供了一个API接口来生成预先签名的urls,用于与S3中的对象交互。
要使用API,首先,您可以创建两个POJO,它们表示我们将从API发送和接收的请求和响应,这样我们就可以用来序列化反序列化JSON信息。
对于请求对象:
public class LinodeGeneratePresignedUrlRequest {
private String method;
private String name;
@JsonProperty("content_type")
private String contentType;
@JsonProperty("expires_in")
private int expiresIn;
// Getters and setters
}对于答复:
pubic class LinodeGeneratePresignedUrlResponse {
private String url;
// Getters and setters
}这些对象匹配端点所需的信息。
如果您想使用Linode API在桶中创建一个对象,那么首先需要请求一个预先签名的URL。一旦获得,您将使用这个URL来执行桶对象上的实际操作。该操作由传递给API的method参数定义。请考虑以下示例:
// Obtain a reference to the RestTemplate instance.
// It should support the interchange of JSON information
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
// Set content type to the one required by the Linode API application/json
headers.setContentType(MediaType.APPLICATION_JSON);
// Set the appropriate credentials for the Linode API
String token = "your token";
headers.set(HttpHeaders.AUTHORIZATION, "Bearer" + token);
// Create the presigned url request
LinodeGeneratePresignedUrlRequest linodeGeneratePresignedUrlRequest =
new LinodeGeneratePresignedUrlRequest();
// Operation to perform when you interact with AWS later
// In this case, PUT because you need to create a new object
linodeGeneratePresignedUrlRequest.setMethod("PUT");
// The object name: can match or not the actual file you want to upload
linodeGeneratePresignedUrlRequest.setName("my-object-name.pdf");
// As you are performing an upload (PUT, POST), indicate the content type of
// the information you are uploading to AWS. It should match the provided later
// when you interact with AWS. For instance, consider that you are uploading a PDF file
linodeGeneratePresignedUrlRequest.setContentType("application/pdf");
// Optionally, you can set the expiration time of the generated presigned url
// By default, an hour (3600 seconds)
// Perform the actual Linode API invocation
HttpEntity<LinodeGeneratePresignedUrlRequest> requestEntity =
new HttpEntity<LinodeGeneratePresignedUrlRequest>(linodeGeneratePresignedUrlRequest, headers);
// The Linode API URL for your cluster and bucket
String linodeApiUrl = "https://api.linode.com/v4/object-storage/buckets/eu-central-1/my-bucket-2020/object-url";
HttpEntity<LinodeGeneratePresignedUrlResponse> responseEntity = restTemplate.exchange(linodeApiUrl, HttpMethod.POST, requestEntity, LinodeGeneratePresignedUrlResponse.class);
// Linde wil provide a response with a property named 'url' corresponding
// to the presigned url that we can use to interact with AWS S3
LinodeGeneratePresignedUrlResponse linodeGeneratePresignedUrlResponse = responseEntity.getBody();
String signedUrl = linodeGeneratePresignedUrlResponse.getUrl();
// Now, send the actual file.
// I am following the example provided in the AWS documentation:
// https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObjectJavaSDK.html adapt for RestTemplate
HttpHeaders headersForS3 = new HttpHeaders();
// You should provide the same content type you indicated previously
headersForS3.set("Content-Type", "application/pdf");
Resource resource = new FileSystemResource("my-object-name.pdf");
HttpEntity<byte[]> requestEntityForS3 =
new HttpEntity<>(
StreamUtils.copyToByteArray(resource.getInputStream()), headersForS3);
// You should use the same HTTP verb as indicated in
// the 'method' parameter before
restTemplate.exchange(signedUrl, HttpMethod.PUT, requestEntityForS3, Void.class);检索创建的对象的过程非常相似:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String token = "your token";
headers.set(HttpHeaders.AUTHORIZATION, "Bearer" + token);
LinodeGeneratePresignedUrlRequest linodeGeneratePresignedUrlRequest =
new LinodeGeneratePresignedUrlRequest();
// Instead of PUT, indicate that you want to retrieve the object
linodeGeneratePresignedUrlRequest.setMethod("GET");
// your object name
linodeGeneratePresignedUrlRequest.setName("my-object-name.pdf");
HttpEntity<LinodeGeneratePresignedUrlRequest> requestEntity =
new HttpEntity<LinodeGeneratePresignedUrlRequest>(linodeGeneratePresignedUrlRequest, headers);
String linodeApiUrl = "https://api.linode.com/v4/object-storage/buckets/eu-central-1/my-bucket-2020/object-url";
HttpEntity<LinodeGeneratePresignedUrlResponse> responseEntity = restTemplate.exchange(linodeApiUrl, HttpMethod.POST, requestEntity, LinodeGeneratePresignedUrlResponse.class);
LinodeGeneratePresignedUrlResponse linodeGeneratePresignedUrlResponse = responseEntity.getBody();
String signedUrl = linodeGeneratePresignedUrlResponse.getUrl();
// Read the object from your bucket
byte[] objectBytes = restTemplate.getForObject(signedUrl, byte[].class);
// And use the information as you need
Files.write(Paths.get("my-object-name.pdf"), objectBytes);当然,如果Linode为您提供了适当的凭据,您也可以使用AWS直接与S3交互。
发布于 2020-12-15 18:48:08
与您提供的cURL命令等效的Spring可以是:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String token = "";
headers.set(HttpHeaders.AUTHORIZATION, token);
JSONObject data = new JSONObject();
data.put("cors_enabled", true);
data.put("acl", "private");
HttpEntity<String> requestEntity = new HttpEntity<String>(data.toString(), headers);
String url = "https://api.linode.com/v4/object-storage/buckets/eu-central-1/bonansa15122020/access";
HttpEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class);在第一个示例中,您还没有提供授权头,所以您将得到401响应。您没有使用您在这里使用RestTemplate创建的RestTemplateBuilder。
在您的第二个示例中,请求体似乎不是JSON (您正在读取logback文件,因此其中不太可能有JSON )。看来Linode API需要一个JSON主体。
发布于 2020-12-17 11:47:24
更新
我相信您可以使用PUT请求作为端点https://api.linode.com/v4/object-storage/buckets/{clusterId}/{bucket}/object-url的POST请求的一部分。
我无法进行测试,因为我没有linode的帐户。
我认为另一个可行的解决方案是为s3使用aws将文件上传到linode端点。
下面是一个简单的例子- code/s3/src/main/java/aws/example/s3/PutObject.java
原版:
基于linode文档,该方法应该是post。
https://www.linode.com/docs/api/object-storage/#object-storage-bucket-create
restTemplate.post("https://api.linode.com/v4/object-storage/buckets", requestEntity, parameters)此外,请检查请求机构,以符合文件。
https://stackoverflow.com/questions/65304541
复制相似问题