我正在使用AWS S3存储桶将用户选择用来更改其个人资料图片的图像存储在S3存储桶中。我可以使用该功能来更新照片,但是,我注意到,刷新页面几秒钟后,图像显示为瞬间破裂,然后加载到页面上。
我的假设是在页面加载时,API还没有时间获取图像数据,因此我研究了React的代码拆分并尝试了基于Route的拆分,但是仍然遇到问题:>
此外,当我也从页面导航到控制台中的另一个页面时,我得到以下消息:https://awss3link/blah-blah-blah/undefined 404 (Not Found)
,即使我在应用程序中声明了附加在链接上的变量,并且图像也正确显示在页面上?
如果需要,我还可以在我的routes.js
文件中包含我使用基于路由的拆分的代码。
这是我的代码:
import React from 'react';
import Header from '../common/Header';
import { Modal, Button } from 'react-bootstrap';
import {Redirect} from 'react-router-dom';
import profileService from '../../services/Profilepage';
class Profilepage extends React.Component {
constructor(props){
super(props);
this.handleClose = this.handleClose.bind(this);
this.handleShow = this.handleShow.bind(this);
this.state = {
redirect: false,
firstName: '',
lastName: '',
email: '',
userName: '',
userId: '',
profilePic: '',
fileObject: '',
fileName: '',
fileType: '',
fileSize: '',
filePayload: '',
errorMsg: false,
errorMsg2: false,
errorMsg3: false,
}
}
handleClose(){
this.setState({
show:false,
// clear file state when modal closes
fileType: '',
fileSize: '',
fileObject: '',
filePayload: ''
});
}
handleShow(){
this.setState({show:true});
}
onChange(e){
var file = e.target.files[0];
var dataTypeURL = new FileReader();
var arrayBuffer = new FileReader();
this.setState({
fileObject: e.target.files[0],
fileName: file.name,
fileSize: file.size,
});
// Scan the file type for it's "magic numbers". to determine the real file type in case user spoofs the file type of the file he is changing.
arrayBuffer.onload = (e) => {
let arr = (new Uint8Array(e.target.result)).subarray(0, 4);
let header = "";
let i;
for(i = 0; i < arr.length; i++){
header += arr[i].toString(16);
}
let truefileType;
switch (header) {
case "89504e47":
truefileType = "image/png";
break;
case "47494638":
truefileType = "image/gif";
break;
case "ffd8ffe0":
case "ffd8ffe1":
case "ffd8ffe2":
case "ffd8ffe3":
case "ffd8ffe8":
truefileType = "image/jpeg";
break;
default:
truefileType = "unknown";
break;
}
this.setState({
fileType: truefileType
});
}
dataTypeURL.onload = (e) => {
this.setState({
filePayload: e.target.result,
profilePic: e.target.result
});
};
dataTypeURL.readAsDataURL(file);
arrayBuffer.readAsArrayBuffer(file);
}
async onSubmit(e){
e.preventDefault();
// file size bytes in mb
var fileCheck = Math.floor(Math.log(this.state.fileSize) / Math.log(1024));
var allowedFileTypes = ['image/jpeg', 'image/jpg', 'image/png'];
//Check if a uploaded photo was taken.
if(this.state.fileObject === ''){
this.setState({
errorMsg: true,
errorMsg2: false,
errorMsg3: false,
})
} else if(!allowedFileTypes.includes(this.state.fileType)){
// check file type
this.setState({
errorMsg: false,
errorMsg2: true,
errorMsg3: false,
})
} else if(fileCheck >= 2){
// check file size
this.setState({
errorMsg: false,
errorMsg2: false,
errorMsg3: true,
})
}
else {
// Change users photo
this.setState({
errorMsg: false,
errorMsg2: false,
errorMsg3: false,
})
//console.log('passed all file checks');
const updateData = {
userName: this.state.userName,
fileType: this.state.fileType,
fileName: this.state.fileName,
fileSize: this.state.fileSize,
filePayload: this.state.filePayload,
}
const updateprofileData = await profileService.updatePhoto(updateData)
//console.log(updateprofileData);
location.href='/Profilepage';
}
}
async selectData(){
if(this.state.profilePic === ''){
await this.setState({isLoading:true})
}
const selectData = {
profilePic: this.state.profilePic,
userName: this.state.userName
}
const selectprofileData = await profileService.selectPhoto(selectData)
await this.setState({
profilePic: 'https://awss3link/blah-blah-blah/' + selectprofileData[0].profilePic
})
}
async componentDidMount(){
await this.userStatus();
await this.selectData();
console.log("Url Params", this.props.match.params);
}
render(){
return (
<div className="container">
<Header />
<div className="row">
<div className="col-md-5" id="profile-left">
{this.props.match.params.userid == this.state.userId ? <h1>Welcome, {this.state.userName}</h1> : <h1>{this.props.match.params.username}</h1> }
<div className="img-rounded">
<img src={this.state.profilePic} alt="profile picture" />
</div>
{this.props.match.params.userid == this.state.userId ? <Button onClick={this.handleShow}>Upload New Photo</Button> : null }
<Modal show={this.state.show} onHide={this.handleClose}>
<form
method="POST"
onSubmit={e => this.onSubmit(e)}
>
<Modal.Header closeButton>
<Modal.Title>Upload New Photo</Modal.Title>
</Modal.Header>
<Modal.Body>
{/* Please upload a photo. */}
{this.state.errorMsg === true ? <span style={{color: 'red'}}>Please upload a photo</span> : null}
{/* Wrong file type. */}
{this.state.errorMsg2 === true ? <span style={{color: 'red'}}>Please upload only JPG or PNG</span> : null}
{/* File is too big. */}
{this.state.errorMsg3 === true ? <span style={{color: 'red'}}>Please upload a file less than 3MB.</span> : null}
<input
type="file"
className="form-control-file"
name="profilePic"
onChange={e => this.onChange(e)}
/>
</Modal.Body>
</form>
</Modal>
</div>
</div>
</div>
)
}
}
export default Profilepage;