Web Applicationを実装します。「Reactを使ってStaticなWeb Hostingをする。」と同じように、まずは、Reactのひな型を作ります。create-react-app upload
cd upload
npm install -save aws-amplify aws-amplify-react
前回作成、または、変更したFileを参考に、S3の設定を追加しながら、作成したひな形にCopyします。詳細な説明は、「Cognitoユーザー認証をAmplifyとReactを使って実装する。(その3)」に戻って確認してください。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import AppWithAuth from './AppWithAuth';
import * as serviceWorker from './serviceWorker';
//Import Amplify Configure function
import { configureAmplify } from './services'
configureAmplify();
ReactDOM.render(<AppWithAuth />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
services.jsでは、S3の設定を追加します。また、SetS3Config()というfunctionを定義します。BucketやS3のAccess Levelを変更した後、AmplifyのStorage.Configure()をCallして、Amplifyの設定を変更する必要があるためです。
import Amplify from '@aws-amplify/core';
import Auth from '@aws-amplify/auth';
import Storage from '@aws-amplify/storage';
export function configureAmplify() {
Amplify.configure(
{
Auth: {
region: process.env.REACT_APP_region,
userPoolId: process.env.REACT_APP_userPoolId,
userPoolWebClientId: process.env.REACT_APP_userPoolWebClientId,
identityPoolId: process.env.REACT_APP_identityPoolId,
},
Storage: {
AWSS3: {
bucket: process.env.REACT_APP_bucket_name,
region: process.env.REACT_APP_region,
}
}
} );
}
//Configure Storage with S3 bucket information
export function SetS3Config(bucket, level){
Auth.configure({
region: process.env.REACT_APP_region,
identityPoolId: process.env.REACT_APP_identityPoolId,
});
Storage.configure({
bucket: bucket,
level: level,
});
}
projectのroot directoryの “.env”にS3の設定を追加した、5つの情報を設定ます。REACT_APP_region=ap-northeast-1
REACT_APP_userPoolId=ap-northeast-1yourPoolID
REACT_APP_userPoolWebClientId=yourWebClientId
REACT_APP_identityPoolId=ap-northeast-1:yourIdentityPoolId
REACT_APP_bucket_name=yourBucketName
AppWithAuth.js、MyVerifyContact.js、MyConfirmSignUp.jsは変更ありません。
import React from 'react';
import { Authenticator, ConfirmSignIn, RequireNewPassword, ConfirmSignUp, VerifyContact, ForgotPassword, TOTPSetup } from 'aws-amplify-react';
import App from "./App";
import MyVerifyContact from "./MyVerifyContact"
import MyConfirmSignUp from "./MyConfirmSignUp"
const signUpConfig = {
hideAllDefaults: true,
signUpFields: [
{
label: 'Username',
key: 'username',
required: true,
placeholder: 'Username',
displayOrder: 1
},
{
label: 'Password',
key: 'password',
required: true,
placeholder: 'Password',
type: 'password',
displayOrder: 2
}
]
}
function AppWithAuth() {
function handleAuthStateChange(state, data) {
if (state === 'confirmSignIn') {
/* Do something when the user has signed-in */
}
}
return (
<Authenticator signUpConfig={signUpConfig} hide={[ConfirmSignIn, RequireNewPassword, VerifyContact, ConfirmSignUp, ForgotPassword, TOTPSetup]} onStateChange={handleAuthStateChange}>
<MyVerifyContact override={VerifyContact} />
<MyConfirmSignUp override={ConfirmSignUp} />
<App />
</Authenticator>
)
}
export default AppWithAuth;
import { AuthPiece } from 'aws-amplify-react';
class MyVerifyContact extends AuthPiece {
constructor(props) {
super(props);
this._validAuthStates = ["verifyContact"];
this.state = {}
}
static getDerivedStateFromProps(props, state) {
if(props.authState === "verifyContact") {
props.onStateChange('signedIn');
return props;
} else {
return null;
}
}
showComponent(theme) {
return null;
}
}
export default MyVerifyContact;
import React from 'react';
import { I18n } from 'aws-amplify';
import { AuthPiece } from 'aws-amplify-react';
import {
FormSection,
SectionHeader,
SectionBody,
SectionFooter,
Button
} from 'aws-amplify-react';
class MyConfirmSignUp extends AuthPiece {
constructor(props) {
super(props);
this._validAuthStates = ["confirmSignUp"];
this.gotoSignIn = this.gotoSignIn.bind(this);
}
gotoSignIn() {
super.changeState('signIn');
}
showComponent(theme) {
return (
<FormSection theme={theme}>
<SectionHeader theme={theme}>{I18n.get('Please contact your administrator to grant your account.')}</SectionHeader>
<SectionBody theme={theme}>
</SectionBody>
<SectionFooter theme={theme}>
<Button onClick={this.gotoSignIn} theme={theme}>
{I18n.get('Goto SignIn')}
</Button>
</SectionFooter>
</FormSection>
);
}
}
export default MyConfirmSignUp;
最後にApp.jsを編集して、S3へUploadできるようにします。
import React, { useState, createRef } from 'react';
import logo from './logo.svg';
import Storage from "@aws-amplify/storage";
import { SetS3Config } from "./services";
import './App.css';
function App(props) {
const [uploadFile, setUploadFile] = useState({});
const [response, setResponse] = useState("");
const uploadRef = createRef();
const onInputClick = () => {
if(uploadRef.current) {
uploadRef.current.value = null;
uploadRef.current.click();
}
setResponse("");
}
function uploadFileToS3() {
SetS3Config(process.env.REACT_APP_bucket_name, "protected");
Storage.put(`upload/${uploadFile.name}`,
uploadFile,
{ contentType: uploadFile.type })
.then(result => {
console.log(result);
setUploadFile({});
setResponse("File is uploaded!");
})
.catch(err => {
console.log(err);
setResponse(`File is not uploaded: ${err}`);
});
};
function InputUploadFile(props) {
return(
<div align="center">
<input
type="file"
style={{ display: "none" }}
accept="image/tif, image/tiff"
ref={uploadRef}
onChange={(e) => setUploadFile(e.target.files[0])}
/>
<input value={uploadFile.name} placeholder="Select file" />
<button onClick={onInputClick}> Browse </button>
<button onClick={uploadFileToS3}> Upload File </button>
{!!response && <div>{response}</div>}
</div>
)
}
if(props.authState === 'signedIn') {
return (
<div className="App">
<InputUploadFile />
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
} else if(props.authState === 'confirmSignUp') {
return (
<div className="Your account is not granted">
<header className="App-header">
Your account is not granted.
</header>
</div>
);
} else if(props.authState === 'signIn') {
return (
<div className="Welcome to the world">
<InputUploadFile />
<header className="App-header">
Welcome to the world.
</header>
</div>
);
} else {
return (
<div className="Login failed">
<header className="App-header">
Login failed.
</header>
</div>
);
}
}
export default App;
npm startからの説明は次回。