取自ThumbSnap
ThumbSnap提供了一个免费的API,可用于以编程方式上传和托管图像和视频。
必填字段:
media-二进制图像/视频数据。应作为多部分/格式数据格式的HTTP POST发送
密钥-ThumbSnap提供的API密钥成功发布图像后,将返回一个JSON格式的文档,其中包含一个“url”,该URL是ThumbSnap上上传照片页面的完整URL。此URL必须链接到应用程序使用的任何ThumbSnap托管的缩略图或图像。
响应示例成功上传图像将返回如下JSON文档:
{
"data": {
"id": "soLHmGdX",
"url": "https://thumbsnap.com/soLHmGdX",
"media": "https://thumbsnap.com/i/soLHmGdX.png",
"thumb": "https://thumbsnap.com/t/soLHmGdX.jpg",
"width": 224,
"height": 224
},
"success": true,
"status": 200
}
我想在Sping Boot 驱动的应用程序中使用此服务,我已转换此响应:
{
"data": {
"id": "soLHmGdX",
"url": "https://thumbsnap.com/soLHmGdX",
"media": "https://thumbsnap.com/i/soLHmGdX.png",
"thumb": "https://thumbsnap.com/t/soLHmGdX.jpg",
"width": 224,
"height": 224
},
"success": true,
"status": 200
}
DTO为:
public record ThumbSnapResponseDTO(
@JsonProperty(value = "data")
DataDTO data,
boolean success,
int status
) {
public record DataDTO(
String id,
String url,
String media,
String thumb,
int width,
int height
) {}
}
接下来是具有以下逻辑的服务类:
@Slf4j
@Service
@RequiredArgsConstructor
public class ThumbSnapServiceImpl implements ThumbSnapService {
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
@Async
@Override
public Future<ThumbSnapResponseDTO> uploadImage(byte[] imageData, String filename) throws IOException {
HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.MULTIPART_FORM_DATA); // First tried this
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // Second this also does not work
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("key", THUMB_SNAP_API_KEY);
body.add("media", new ByteArrayResource(imageData) {
@Override
public String getFilename() {
return filename;
}
});
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
restTemplate.getMessageConverters().add(new MultiPartMessageConverter(objectMapper));
ResponseEntity<ThumbSnapResponseDTO> response =
restTemplate.exchange(
THUMB_SNAP_BASE_URL,
HttpMethod.POST,
requestEntity,
ThumbSnapResponseDTO.class
);
CompletableFuture<ThumbSnapResponseDTO> future = new CompletableFuture<>();
log.info("REST RESPONSE {} ", response.getBody());
future.complete(response.getBody());
return future;
}
}
最后但并非最不重要的是实际使用此服务的Controller方法:
// ThumbSnap
private final ThumbSnapService thumbSnapService;
@Override
@PostMapping("/{portfolioId}/upload")
public ResponseEntity<?> saveToThumbSnap(
@PathVariable(name = "portfolioId") Long portfolioId,
@RequestPart("media") MultipartFile file
) throws ExecutionException, InterruptedException, IOException {
// Logign
String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
long size = file.getSize();
log.info("File is {} - - and size is {} ", fileName, size);
// Get Data as bytes
byte[] imageData = file.getBytes();
Future<ThumbSnapResponseDTO> response = thumbSnapService.uploadImage(imageData, fileName);
ThumbSnapResponseDTO result = response.get();
var portfolio = portfolioService.findById(portfolioId).orElseThrow(
() -> new EntityNotFoundException(String.format("Record not found with id = %s", portfolioId))
);
// Check if Image Uploaded Successfully
if (!result.success())
throw new RuntimeException("Unable to upload image CONTROLLER");
var portfolioItemImage = new PortfolioItemImage();
//set img URL
portfolioItemImage.setImgUrl(result.data().url());
// Save mapping
portfolioItemImage.setPortfolio(portfolio);
return ResponseEntity.status(HttpStatus.OK).body(
portfolioItemImageMapper.asDTO(portfolioItemImageService.save(portfolioItemImage))
);
}
当我在PostMan REST客户端中尝试将post请求发送到上述端点时,我得到了错误:
{
"code": "EXECUTION",
"message": "org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: \"No API key specified. Upload stopped\""
}
屏幕截图如下:
我已经检查了API_KEY无数次,但是没有效果。
问题是:
下面的代码是否有问题:
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("key", THUMB_SNAP_API_KEY);
body.add("media", new ByteArrayResource(imageData) {
@Override
public String getFilename() {
return filename;
}
});
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
restTemplate.getMessageConverters().add(new MultiPartMessageConverter(objectMapper));
ResponseEntity<ThumbSnapResponseDTO> response =
restTemplate.exchange(
THUMB_SNAP_BASE_URL,
HttpMethod.POST,
requestEntity,
ThumbSnapResponseDTO.class
);
或者有任何其他的方法来完成这一点。我怎样才能正确地发送请求,你能请建议一个解决方案吗?
1条答案
按热度按时间wswtfjt71#
至于上面的代码,除了
@PostMapping
之外,其他一切看起来都很好。您必须按如下所示更改该行:consume属性用于指定方法可以在请求正文中处理的媒体类型。
MediaType.MULTIPART_FORM_DATA_VALUE
值表示方法可以接受 multipart/form 数据格式的数据,该格式通常用于文件上载操作,而MediaType.APPLICATION_JSON_VALUE
值表示方法可以返回application/json
的数据。现在它应该按预期/预期工作。