AWS s3로 파일 업로드
09 Oct 2020 | memoAWS s3로 파일 업로드
aws s3란?
- S3란 Simple Storage Service의 약자로 쉽게말해 파일을 저장하는 저장소
aws s3 버킷 생성 및 id와 key얻기
npm i aws-sdk multer-s3
-
버킷을 생성하면 엑세스가 퍼블릭으로 되있지않을텐데 왼쪽 메뉴에서 퍼블릭계정권한 탭에서 해제하여 퍼블릭으로 바꿔주면된다.
-
이후 aws 서비스 탭에서
IAM
을 눌러 사용자추가를 해준다- 사용자 추가를 할때 맨 아래 AWS 액세스 유형 방식에서 프로그래밍 방식 액세스를 체크해준후 다음 탭 클릭
- (액세스 방식을 사용할것이기 때문)
-
권한 설정 페이지에서
기존 정책 직접 연결
을 눌러 S3를 검색,AmazonS3FullAccess 체크후 다음 탭 클릭후 한번 더 다음 탭 클릭후 사용자 만들기 탭 클릭 -
이후 access key ID 와 Secret access key가 보여지는 페이지가 나오는데, 이 화면을 떠나면 더이상 여기에 접근할 수 가없기때문에 따로 적어줘야한다.
aws s3에 Multer로 파일 업로드하기
기존 multer를 활용한 코드에서 multer-s3로 바꿔준다. 몇몇의 수정사항이있으니 기존코드와 수정 코드 둘다 올려놓겠다.
기존 multer를 활용한 코드
const multer = require('multer');
//=================================
// (게시글이미지업로드)
//=================================
var multerImage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/images');
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}_${file.originalname}`);
},
});
//=================================
// (프로필이미지업로드)
//=================================
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/avatar');
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}_${file.originalname}`);
},
});
var imageUpload = multer({ storage: multerImage }).single('file');
var avatarUpload = multer({ storage: storage }).single('file');
// module.exports = upload;
exports.avatarUpload = avatarUpload;
exports.imageUpload = imageUpload;
수정된 multer-s3 코드
- server/middleware/upload
const multer = require('multer');
const multerS3 = require('multer-s3');
const aws = require('aws-sdk');
//=================================
// (게시글이미지업로드)
//=================================
const s3 = new aws.S3({
accessKeyId: process.env.AWS_KEY,
secretAccessKey: process.env.AWS_PRIVATE_KEY,
});
var imageUpload = multer({
storage: multerS3({
s3: s3,
acl: 'public-read',
bucket: 'gongcha/uploadImage',
contentType: multerS3.AUTO_CONTENT_TYPE,
metadata: function (req, file, cb) {
cb(null, { fileName: file.fieldname });
},
key: function (req, file, cb) {
var filename = file.originalname;
var ext = file.mimetype.split('/')[1];
if (!['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(ext)) {
return cb(new Error('Only images are allowed'));
}
cb(null, Date.now().toString() + filename);
},
}),
}).single('file');
var avatarUpload = multer({
storage: multerS3({
s3: s3,
acl: 'public-read-write',
bucket: 'gongcha/avatarImage',
contentType: multerS3.AUTO_CONTENT_TYPE,
metadata: function (req, file, cb) {
cb(null, { fileName: file.fieldname });
},
key: function (req, file, cb) {
var filename = file.originalname;
var ext = file.mimetype.split('/')[1];
if (!['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(ext)) {
return cb(new Error('Only images are allowed'));
}
cb(null, Date.now().toString() + filename);
},
}),
}).single('file');
// module.exports = upload;
exports.avatarUpload = avatarUpload;
exports.imageUpload = imageUpload;
exports.s3 = s3;
- server/routes/api/users.js
- 기존에 file.path였지만,file.location로 변경해줘야 받을 수 있다.
// @route POST api/users/edit/avatar (프로필 이미지 편집)
// @desc AvatarChange user
// @access Private
router.post('/edit/avatar', async (req, res) => {
// 프론트 에서 가져온 이미지를 저장을 해준다.
upload.avatarUpload(req, res, (err) => {
if (err) {
return res.json({ success: false, err });
}
if (!req.file) return res.send('Please upload a file');
return res.json({
success: true,
filePath: res.req.file.location,
fileName: res.req.file.originalname,
});
});
});
-
이후 프론트에서 이미지를 불러올때 기존의 코드는가
<img src={`http://localhost:5000/${user.avatar}`} alt='userAvatar' />
이랬다면, 이렇게 바꿔줘야한다.
<img src={user.avatar} alt='userAvatar' />
s3에 파일 업로드된거 삭제 해주기
☆★☆★ 파일명 꼭 영어로 해주기☆★☆★
s3는 한글명으로하면 에러난다고함 그리고 작동안함
실제로 이 문제 때문에 꼬박 하루 고생했음
// @route DELETE api/posts/:id
// @desc 게시글 지우기
// @access Private
router.delete('/:id', auth, async (req, res) => {
try {
const post = await Post.findById(req.params.id);
const user = await User.findById(req.user.id).select('-password');
if (!post) {
return res.status(404).json({ msg: '게시글이 없습니다.' });
}
// aws s3 버킷에서 파일 삭제
const url = post.image.split('/'); // post에 저장된 image를 가져옴
const delFileName = url[url.length - 1];
const params = {
Bucket: 'gongcha',
Key: `uploadImage/${delFileName}`,
};
upload.s3.deleteObject(params, function (err, data) {
console.log(params);
if (err) {
console.log('aws image delete error');
console.log(err, err.stack);
return;
} else {
console.log('aws image delete success' + data);
}
});
// check user
if (post.user.toString() !== req.user.id) {
return res.status(401).json({ msg: '게시글을 작성한 유저가 아닙니다.' });
}
const userPost = user.posts.filter(
(post) => post._id.toString() !== req.params.id
);
// Get remove index
const removeIndex = user.posts
.map((post) => post._id.toString())
.indexOf(req.user.id);
user.posts.splice(removeIndex, 1);
await user.save();
await post.remove();
res.json({ msg: '게시글 삭제 완료' });
} catch (err) {
if (err.kind === 'ObjectId') {
return res.status(404).json({ msg: '게시글을 찾을 수 없습니다.' });
}
res.status(500).send('Server Error');
}
});