How to display images from amazon s3 bucket in react? Images are not being displayed using amazon s3,spring boot 2.5.3,react.
I have tested the end points in postman, it works.
React: Using Axios to connect to backend and MyDropZone
Using axios to make a post request, I can confirm that images are being saved in s3.

This is the reponse after making a post request, for the first 2 user.
[
{
"userId":"565c6cbe-7833-482d-b0d4-2edcd7fc6163",
"userName":"John",
"imageUrl":"pexels-photo-3147528.jpeg"
},
{
"userId":"3c776990-38e8-4de4-b7c6-7875c0ebb20f",
"userName":"Anthony",
"imageUrl":"pexels-photo-3147528.jpeg"
},
{
"userId":"bcac9cf2-5508-4996-953e-b18afe866581",
"userName":"Peter",
"imageUrl":null
}
]
React:
import './App.css';
import axios from 'axios';
import { useState, useEffect,useCallback } from 'react';
import {useDropzone} from 'react-dropzone'
//
const UserProfiles = () => {
const [userProfiles,setUserProfiles]=useState([])
const fetchUserProfiles=() => {
axios.get('http://localhost:5000/api/v1/users').then((response) => {
console.log(response.data)
setUserProfiles(response.data)
})
}
useEffect(() => {
fetchUserProfiles();
}, [])
return userProfiles.map((profile,index) => {
return (
<div key={index}>
<MyDropZone userId={profile.userId}></MyDropZone>
<h3>{profile.userId}</h3>
{
profile.userId ? (<img src={`http://localhost:5000/api/v1/users/${profile.userId}/image/download`} /> ) : <h5>No profile Image Uploaded</h5>
}
</div>
);
})
}
function MyDropZone({userId}) {
const onDrop = useCallback(acceptedFiles => {
// Do something with the files
console.log(acceptedFiles[0])
const file=acceptedFiles[0]
//Form-data
const formData = new FormData()
formData.append('file', file)
//Make a post req
axios.post(`http://localhost:5000/api/v1/users/${userId}/image/upload`, formData, {
headers: {
'Content-Type':'multipart/form-data'
}
}).then((response) => {
console.log(response)
console.log("Uploaded")
}).catch((error) => {
console.log(error)
})
}, [])
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop the files here ...</p> :
<p>Drag 'n' drop some files here, or click to select files</p>
}
</div>
)
}
function App() {
return (
<div className="App">
<UserProfiles ></UserProfiles>
</div>
);
}
export default App;
The image is not being loaded in the UI.
{
profile.userId ? (<img src={`http://localhost:5000/api/v1/users/${profile.userId}/image/download`} /> ) : <h5>No profile Image Uploaded</h5>
}
When I go to this http://localhost:5000/api/v1/users/565c6cbe-7833-482d-b0d4-2edcd7fc6163/image/download URL via browser.
It has a response with
ÿØÿàJFIFHHÿâICC_PROFILElcmsmntrRGB XYZ Ü)9acspAPPLöÖÓ-lcms descü^cprt\wtpthbkpt|rXYZgXYZ¤bXYZ¸rTRCÌ@gTRCÌ@b
Update Added Backend code.
controller
@GetMapping(path = "{userId}/image/download")
public byte[] downloadUserProfileImage(@PathVariable("userId") UUID userId) {
return userProfileService.downloadUserProfileImage(userId);
}
Service:
private UserProfile getUserProfileOrThrow(UUID userId) {
UserProfile userProfile = userProfileRepository.getUserProfiles()
.stream()
.filter(profile -> profile.getUserId().equals(userId)).findFirst().orElseThrow(() -> new IllegalStateException("User does not exist" + userId)
);
return userProfile;
}
public byte[] downloadUserProfileImage(UUID userId) {
UserProfile userProfile=getUserProfileOrThrow(userId);
String path = String.format("%s/%s",
BucketName.PROFILE_IMAGE.getBucketName(),
userProfile.getUserId());
return userProfile.getImageUrl()
.map(key -> fileStore.download(path, key))
.orElse(new byte[0]);
}
FileStore:
@Service
public class FileStore {
private final AmazonS3 s3;
@Autowired
public FileStore(AmazonS3 s3) {
this.s3 = s3;
}
public void save(String path,
String fileName,
Optional<Map<String, String>> optionalMetadata,
InputStream inputStream) {
ObjectMetadata metadata = new ObjectMetadata();
optionalMetadata.ifPresent(map -> {
if (!map.isEmpty()) {
map.forEach(metadata::addUserMetadata);
}
});
try {
s3.putObject(path, fileName, inputStream, metadata);
} catch (AmazonServiceException e) {
throw new IllegalStateException("Failed to store file to s3", e);
}
}
public byte[] download(String path, String key) {
try {
S3Object object = s3.getObject(path, key);
return IOUtils.toByteArray(object.getObjectContent());
} catch (AmazonServiceException | IOException e) {
throw new IllegalStateException("Failed to download file to s3", e);
}
}
}
Amazon s3 config: @Configuration public class AmazonConfig {
@Bean
public AmazonS3 s3(){
AWSCredentials awsCredentials=new BasicAWSCredentials("my-credentials","my-secret-key");
return AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(Regions.AP_SOUTH_1)
.build();
}
}
UserProfile:
public class UserProfile {
private final UUID userId;
private final String userName;
private String imageUrl;
//This might be null
public Optional<String> getImageUrl() {
return Optional.ofNullable(imageUrl);
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
//getters & setters
}
