如何在 React 中显示来自 amazon s3 bucket 的图像? 图像未使用 amazon s3、spring boot 2.5.3、react 显示。
我已经在 postman 中测试了端点,它有效。
React:使用 Axios 连接后端和 MyDropZone
使用 axios 发出 post 请求,我可以确认图像正在保存在 s3 中。
这是前 2 位用户发出发布请求后的响应。
[
{
"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;
图像未加载到 UI 中。
{
profile.userId ? (<img src={`http://localhost:5000/api/v1/users/${profile.userId}/image/download`} /> ) : <h5>No profile Image Uploaded</h5>
}
当我通过浏览器转到此 http://localhost:5000/api/v1/users/565c6cbe-7833-482d-b0d4-2edcd7fc6163/image/download
URL 时。
它有一个回应
ÿØÿàJFIFHHÿâICC_PROFILElcmsmntrRGB XYZ Ü)9acspAPPLöÖÓ-lcms descü^cprt\wtpthbkpt|rXYZgXYZ¤bXYZ¸rTRCÌ@gTRCÌ@b
更新添加的后端代码。
Controller
@GetMapping(path = "{userId}/image/download")
public byte[] downloadUserProfileImage(@PathVariable("userId") UUID userId) {
return userProfileService.downloadUserProfileImage(userId);
}
服务:
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]);
}
文件存储:
@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);
}
}
}
亚马逊 s3 配置: @配置 公共(public)类 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();
}
用户资料:
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
}
最佳答案
当我遇到同样的问题时,我不得不以 Base64
格式返回 object.getObjectContent()
图像。
之后在前端展示数据的时候,可以这样尝试:
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
你可以试试this Base64 decoder查看您的 Base64 数据是否正确。
这意味着您事先进行了 GET 调用,保存结果,然后在 img src
中显示 base64 字符串
更新:
根据您的方法,为了下载每个用户配置文件的图像,在 .map
中,您可以有一个为每个配置文件下载图片的函数。
const fetchUserProfileImage = async (userProfileId) => {
return axios.get(`http://localhost:5000/api/v1/users/${profile.userId}/image/download`)
}
return userProfiles.map(async (profile,index) => {
const userProfileImageBase64 = await fetchUserProfileImage(profile.userId)
return (
<div key={index}>
<MyDropZone userId={profile.userId}></MyDropZone>
<h3>{profile.userId}</h3>
{
profile.userId ? (<img src={`data:image/png;base64, ${userProfileImageBase64}`}/> ) : <h5>No profile Image Uploaded</h5>
}
</div>
);
})
或者如果您不喜欢在 .map
中等待,您可以尝试在渲染主体之前下载所有图像并将它们映射到 中已经存在的用户userProfiles
状态。
或者,我认为最好的方法是将另一个 profileImageSrc
字段添加到 User
类,并在您在后端上传图像时将其保存在那里。然后您不必进行额外的调用,只需使用在获取 userProfiles
关于reactjs - 如何使用 spring boot 显示来自 AWS s3 的图像并使用react?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68936315/