Heroku Gitė ėīėĐí ë°Đëēė ėīėī githubëĨž ėīėĐíī ë°ëĄ Herokuė ë°°íŽí ėë ėëĪ.
git push origin main í  ëë§ëĪ ėëėžëĄ ëđëę° ëĪė ėėëëĐīė ë°°íŽę° ëëĪ.
git push heroku main ė ė
ë Ĩí  íėę° ėėī ę°íļíė§ë§ ėĢžėę° íėíëĪ.
íėŽ ėëēëĨž íėž ė ėĨėëĄ ėŽėĐíęģ  ėëĪ.
ėī ëëŽļė ėąė ë°°íŽí  ëë§ëĪ(git push ~) ëđëę° ëĪė ėėëžė ėđ ėŽėīíļė ė
ëĄëëėī ėë ë°ėīí°ëĪ(ëđëėĪ, íëĄí ėŽė§)ėī ëŠĻë ėŽëžė§ęē ëëĪ.
ëŽļė ëĨž íīęē°íęļ° ėíī AWSëĨž ėīėĐí ė ėëĪ.
ęģė ė ë§ë  í service - storage - s3ëĄ ėīëíėŽ create bucket ëēížė íīëĶíëĪ.
ëēí· ėīëĶė ėėąíęģ  ė§ėė ėėļëĄ ė íí í ëēí·ė ë§ë ëĪ.
node.js ėëēę° AWSė ėīėžęļ°í  ė ėëëĄ API keyëĨž ë§ëĪėīėž íëĪ.
IAMė ęēėíī ėŽėĐė(users) íėīė§ėė ėŽėĐė ėķę° ëēížė íīëĶíëĪ.
user nameė ęļ°ėĩí  ė ėë ë§íž ęļļęē ėėąí í ėĄėļėĪ íĪ - íëĄę·ļëë° ë°Đė ėĄėļėĪëĨž ė ííëĪ.
ęķíė ėĪė íęļ° ėíī ëĪė íėīė§ëĄ ëėīę°ė AmazonS3FullAccessëĨž ęēėíī ėīëĨž ė ííëĪ.
ėīë S3ėė í  ė ėë ëŠĻë  ęķí ėĶ, íėžė ė
ëĄëí  ė ėë ęķíė ëķėŽíë ęēėīëĪ.
íėŽ ë§ëĪęģ  ėë ęģė ėžëĄë ėīęēë§ í  ė ėëëĄ íë ęēėīëĪ.
íę·ļë ėĪė í  íė ėęģ  ëĪė í ëē ė ėēī ė í ëīėĐė íėļí íė 'ėŽėĐė ë§ëĪęļ°' ëēížė íīëĶíëĪ.
ėīë ęē ë§ë ėĄėļėĪ íĪë í ëēë°ė ëģž ė ėęļ° ëëŽļė ėĶė ėīëĨž ëģĩėŽíīė Heroku ėŽėīíļė Settingsė íëĄė íļ íīëė .env íėžė ėķę°íëĪ. (AWS_ID & AWS_SECRET)
multer-s3 ė°ļęģ
multer S3 íĻíĪė§ëĨž ėīėĐíëĐī íėžė ėđ ėŽėīíļ ėëē ëė  AWSė ė
ëĄëí  ė ėëĪ.
íėžė ė
ëĄëí  ë íėž ėėĪí
 ëė  AWSëĨž ėŽėĐíë ęēėīëĪ.
$ npm i multer-s3
multer ëŊļëĪėĻėīę° ėë middlewares.js íėžė ėė íīėž íëĪ.
aws-sdk íĻíĪė§ëĨž ėĪėđíī s3 objectëĨž ë§ë ëĪ.
ėīë ėĩė
ėžëĄ ėė Herokuė Settingsė .env íėžė ėķę°í AWS_IDė AWS_SECRETė ė íīėĪėž íëĪ.
$ npm i aws-sdk
// middlewares.js
import aws from "aws-sdk";
import multerS3 from "multer-s3";
const s3 = new aws.S3({
  credentials: {
    accessKeyId: process.env.AWS_ID,
    secretAccessKey: process.env.AWS_SECRET
  }
});
ėīëĨž ë°íėžëĄ multerS3ëĨž ë§ë ëĪ.
uploadAvatarė uploadVideo ëŊļëĪėĻėīė storageëĨž ėķę°íëĪ.
// middlewares.js
const multerUploader = multerS3({
    s3: s3,
    bucket: "ëēí· ėīëĶ",
});
export const uploadAvatar = multer({
  dest: "uploads/avatars/",
  limit: {
    fileSize: 5000000,
  },
  storage: multerUploader, // ėķę°
});
export const uploadVideo = multer({
  dest: "uploads/videos/",
  limits: {
    fileSize: 10000000,
  },
  storage: multerUploader, // ėķę°
});
ėđ ėŽėīíļėė íëĄí ėŽė§ė ėė íëĪ.
ę·ļëŽë ėëŽę° ë°ėíīė ėđ ėŽėīíļėė ėŽė§ėī ė ëëĄ ëģīėīė§ ėëëĪ.
ëĪë§, ëēí·ė íėļíīëģīëĐī ę°ėēīę° ėęļī ęēė íėļí  ė ėëĪ.
íėžė ė
ëĄëí  ë ë ėīė ëī ėŧīíĻí°ė íīëė ė ėĨíė§ ėęģ  AWSëĨž ėŽėĐíë ęēėīëĪ!
(ë°Đęļ ė ëĄëí íėžė ęģĩę°ëė§ ėėė íė ėęļ° ëëŽļė ëēí·ėė ėė íīėĪëĪ.)
ė
ëĄëí íėžė ėđ ėŽėīíļėė ė ëëĄ ëģž ė ėëëĄ íęļ° ėíī ė
ëĄëë íėžëĪė ęģĩę°íīėž íëĪ.
'ëēí· - ęķí - ížëļëĶ ėĄėļėĪ ė°ĻëĻ(ëēí· ėĪė )'ėžëĄ ėīëíëĪ.
'ė ížëļëĶ ëēí· ëë ėĄėļėĪ ė§ė  ė ėą
ė íĩíī ëķėŽë ëēí· ë° ę°ėēīė ëí ížëļëĶ ėĄėļėĪ ė°ĻëĻ'ęģž 'ėėė ížëļëĶ ëēí· ëë ėĄėļėĪ ė§ė  ė ėą
ė íĩíī ëķėŽë ëēí· ë° ę°ėēīė ëí ížëļëĶ ë° ęĩė°Ļ ęģė  ėĄėļėĪ ė°ĻëĻ'ë§ ę·ļëëĄ íėąí ėíëĄ ëęģ , ACLsė ęīë Ļë ëīėĐė ëđíėąí íëĪ.
ëĪėėžëĄ, Access Control List(ACL)ëĨž ė ëŽíīėž íëĪ.
ëęĩŽë íėžė ė―ė ė ėëëĄ public-readëĄ ė ëŽíīėž íëĪ.
// middlewares.js
const multerUploader = multer({
  s3: s3,
  bucket: "ëēí· ėīëĶ",
  acl: "public-read", // ėķę°
});
ííļ, íėžė ė
ëĄë í  ëë§ëĪ users DBëĨž íėļíīëģīëĐī avatarUrlėī null ę°ė ę°ė§ë ęēė íėļí  ė ėëĪ.
ėëŽė ėėļė íė
íęļ° ėíī userController.jsėė postEdit ėŧĻíļëĄĪëŽëĨž ėīíīëģīëĐī ëĪėęģž ę°ëĪ.
// userController.js
export const postEdit = async (req, res) => {
  const updatedUser = await User.findByidAndUpdate(
    _id,
    {
      avatarUrl: file ? file.path : avatarUrl,
      // ėĪëĩ
    },
  );
  
};
avatarUrlėī null ę°ėīëžë ęēė file.pathėī nullėīëžë ëŧėīëĪ.
console.log(file)ëĨž íīëģīëĐī, fileė ë ėīė pathëĨž ę°ė§ęģ  ėė§ ėęģ  locationė ę°ė§ęģ  ėėžëŊëĄ ęīë Ļ ė―ëëĨž ëŠĻë ėė íīėž íëĪ.
ëí, pug íėžėė íėž srcė ęīë Ļíī loggedInUser.avatarUrl ėė ëķėë "/"ëĪė ëŠĻë ėė íëëĄ íëĪ.
ę·ļëŽë ėŽęļ°ęđė§ íīë ėëŽę° ë°ėíëĪ.