Closed 10ky closed 5 years ago
The changes required should not be much, something like this:
/*
* Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
import * as React from 'react';
import { Component } from 'react';
import { ConsoleLogger as Logger } from '@aws-amplify/core';
import Storage from '@aws-amplify/storage';
import AmplifyTheme from '../AmplifyTheme';
import { transparent1X1 } from '../AmplifyUI';
import PhotoPicker from '../Widget/PhotoPicker';
import { calcKey } from './Common';
const logger = new Logger('Storage.S3Image');
export default class S3Image extends Component {
constructor(props) {
super(props);
this.handleOnLoad = this.handleOnLoad.bind(this);
this.handleOnError = this.handleOnError.bind(this);
this.handlePick = this.handlePick.bind(this);
this.handleClick = this.handleClick.bind(this);
const initSrc = this.props.src || transparent1X1;
this.state = { src: initSrc };
}
getImageSource(key, level, customPrefix, track) {
if (!Storage || typeof Storage.get !== 'function') {
throw new Error('No Storage module found, please ensure @aws-amplify/storage is imported');
}
Storage.get(key, {
customPrefix: customPrefix ? customPrefix : { public: 'public', protected: 'protected', private: 'private' },
level: level ? level : 'public',
track
})
.then(url => {
this.setState({
src: url
});
})
.catch(err => logger.debug(err));
}
load() {
const { imgKey, path, body, contentType, level, customPrefix, track } = this.props;
if (!imgKey && !path) {
logger.debug('empty imgKey and path');
return;
}
const that = this;
const key = imgKey || path;
logger.debug('loading ' + key + '...');
if (body) {
const type = contentType || 'binary/octet-stream';
if (!Storage || typeof Storage.put !== 'function') {
throw new Error('No Storage module found, please ensure @aws-amplify/storage is imported');
}
const ret = Storage.put(key, body, {
contentType: type,
level: level ? level : 'public',
track
});
ret.then(data => {
logger.debug(data);
that.getImageSource(key, level, customPrefix, track);
})
.catch(err => logger.debug(err));
} else {
that.getImageSource(key, level, customPrefix, track);
}
}
handleOnLoad(evt) {
const { onLoad } = this.props;
if (onLoad) { onLoad(this.state.src); }
}
handleOnError(evt) {
const { onError } = this.props;
if (onError) { onError(this.state.src); }
}
handlePick(data) {
const that = this;
const path = this.props.path || '';
const { imgKey, level, fileToKey, track } = this.props;
const { file, name, size, type } = data;
const key = imgKey || (path + calcKey(data, fileToKey));
if (!Storage || typeof Storage.put !== 'function') {
throw new Error('No Storage module found, please ensure @aws-amplify/storage is imported');
}
Storage.put(key, file, {
level: level ? level : 'public',
contentType: type,
track
})
.then(data => {
logger.debug('handle pick data', data);
that.getImageSource(key, level, getImageSource, track);
})
.catch(err => logger.debug('handle pick error', err));
}
handleClick(evt) {
const { onClick } = this.props;
if (onClick) { onClick(evt); }
}
componentDidMount() {
this.load();
}
componentDidUpdate(prevProps) {
const update = prevProps.path !== this.props.path ||
prevProps.imgKey !== this.props.imgKey ||
prevProps.body !== this.props.body;
if (update) {
this.load();
}
}
imageEl(src, theme) {
if (!src) { return null; }
const { selected } = this.props;
const containerStyle = { position: 'relative' };
return (
<div style={containerStyle} onClick={this.handleClick}>
<img
style={theme.photoImg}
src={src}
onLoad={this.handleOnLoad}
onError={this.handleOnError}
/>
<div style={selected ? theme.overlaySelected : theme.overlay}></div>
</div>
);
}
render() {
const { hidden, style, picker, translate, imgKey } = this.props;
let src = this.state.src;
if (translate) {
src = (typeof translate === 'string') ? translate : translate({
type: 'image',
key: imgKey,
content: src
});
}
if (!src && !picker) { return null; }
const theme = this.props.theme || AmplifyTheme;
const photoStyle = hidden ? AmplifyTheme.hidden
: Object.assign({}, theme.photo, style);
return (
<div style={photoStyle}>
{photoStyle ? this.imageEl(src, theme) : null}
{picker ? <div>
<PhotoPicker
key="picker"
onPick={this.handlePick}
theme={theme}
/>
</div> : null
}
</div>
);
}
}
@10ky Have you tried using Storage.configure() to set the customPrefix?
Just tried this:
Storage.configure({
customPrefix: { public: 'public/', protected: 'protected/', private: 'private_resized/' }
})
Also updated my IAM role for auth user:
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::photos/public/*",
"arn:aws:s3:::photos/protected/${cognito-identity.amazonaws.com:sub}/*",
"arn:aws:s3:::photos/private_resized/${cognito-identity.amazonaws.com:sub}/*",
"arn:aws:s3:::photos/private/${cognito-identity.amazonaws.com:sub}/*"
],
"Effect": "Allow"
},
After that, it worked. Thanks for that pointer. It make more sense to put the customPrefix support in Storage.configure().
This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.
Looking for a help forum? We recommend joining the Amplify Community Discord server *-help
channels or Discussions for those types of questions.
Which Category is your question related to? AWS Amplify S3Image
What AWS Services are you utilizing? S3
Provide additional details e.g. code snippets I can put a photo to S3 using customPrefix:
I want to show the photo using S3Image like so:
S3Image currently does not support customPrefix:
https://github.com/aws-amplify/amplify-js/blob/88ccc4f680d616751d679299dc9740af115332e8/packages/aws-amplify-react/src/Storage/S3Image.js
If it is not a security risk to add customPrefix, please consider adding this feature.