简体   繁体   English

如何在注册用户之前检查用户凭据,同时将图像上传到 aws s3

[英]How to check user credentials before registering a user while also uploading an image to aws s3

I am trying to implement a registration route in my application.我正在尝试在我的应用程序中实施注册路线。 The flow is pretty simple.流程非常简单。 While using the application, the user has the opportunity to select a profile image (but he doesn't have to).在使用应用程序时,用户有机会选择个人资料图片(但他没有必要这样做)。 Later on, the user is asked to register and enters an email.稍后,要求用户注册并输入电子邮件。

Now, I would like to check on my registration route IF the email already exists BEFORE uploading the image to my S3 bucket.现在,在将图像上传到我的 S3 存储桶之前,如果电子邮件已经存在,我想检查我的注册路线。 If it does exist, I want to send back a proper error message.如果确实存在,我想发回正确的错误消息。 If it does NOT exist, I would like to check if the user has send along an image and proceed to upload the image to S3 so I can store the link in my db and proceed to register the user.如果它不存在,我想检查用户是否已发送图像并继续将图像上传到 S3,以便我可以将链接存储在我的数据库中并继续注册用户。

The Problem问题

Im appending both the file and the email to a formData object like so.我将文件和电子邮件都附加到这样的 formData 对象中。 At this point the file can be empty.此时file可以为空。 That depends if the user has selected a profile image or not.这取决于用户是否选择了个人资料图片。

const formData = new FormData();
formData.append('avatar', this.variables.avatar);
formData.append('email', JSON.stringify(this.email));

The problem is that when making the request, either req.file is undefined or req.body.email is undefined.的问题是,在进行请求时,无论是req.file是未定义或req.body.email未定义。 The reason for this is simple, I cannot acces the req.body.email BEFORE the image is uploaded to my s3 bucket.原因很简单,在图像上传到我的 s3 存储桶之前,我无法访问req.body.email This would mean that everytime a user registers with an already existing email, the image gets send to my s3 bucket nonetheless.这意味着每次用户使用现有电子邮件注册时,图像仍会发送到我的 s3 存储桶。

This is my function to upload to aws:这是我上传到 aws 的功能:

const avatarImgUpload = multer({
  storage: multerS3({
    s3: s3,
    bucket: process.env.AWS_BUCKET,
    acl: 'public-read',
    key: function (req, file, cb) {
      cb(null, path.basename(file.originalname, path.extname(file.originalname)) + '-' + Date.now() + path.extname(file.originalname))
    }
  }),
}).single('avatar');

And this is my register route:这是我的注册路线:

router.post('/register', (req, res) => {
  //let email = JSON.parse(req.body.email);
  //The email is undefined because I am not using middleware 
  //like multer to be able to 'read' or 'acces' this

  //Ideally I would like to FIRST check if a user exists like so:
  //User.findOne({email: req.body.email})

  //If it does not exists, great! Continue to the 'avatarImgUpload' function that uploads to S3'
  //If not, send back an error message and end the request there.

  avatarImgUpload(req, res, (error) => {
    //Within this function I do have access to req.body.email because it uses multer.
    //However, like I said before this means that the check IF the user already exists
    //has to take place AFTER the image is uploaded to my S3 bucket, which isn't great.
  })
})

Is there a way around this?有没有解决的办法? Can I get acces to req.body.email BEFORE uploading the image to my S3 bucket?在将图像上传到我的 S3 存储桶之前,我可以访问req.body.email吗? Is there a way for example to maybe both send a formData object AND JSON so I can first check the email before continuing with the file upload?例如,有没有办法同时发送一个formData对象和JSON这样我就可以在继续上传文件之前先检查电子邮件?

Just split it into 2 requests, let user thinks it's just 1 operation using AJAX:只需将其拆分为 2 个请求,让用户认为它只是使用 AJAX 的 1 个操作:

  1. Check User condition检查用户条件
  2. If matched, allow to register and upload.如果匹配,允许注册和上传。

For more secure, Presigned Url works well.为了更安全,预签名网址效果很好。 Signed url is like a temporary link with temporary permission used to upload to your S3, without this link, user cannot upload to your S3.签名 url 就像一个临时链接,用于上传到您的 S3 的临时权限,没有此链接,用户无法上传到您的 S3。 Basically, the flow will be:基本上,流程将是:

  1. User requests to server to check condition and get signed url -> if matched, server responses with an url.用户请求服务器检查条件并获得签名的 url -> 如果匹配,服务器响应一个 url。

Not sure as if multer supports getting signed url, this code is using aws sdk:不确定 multer 是否支持获取签名的 url,此代码使用的是 aws sdk:

router.post('/register', (req, res) => {
  // Check User exists
  // ...

  // Set custom info for the uploading image
  const fileName = uuid();
  const s3 = new S3();
  const params = {
    Bucket: 'bucket name',
    Key: 'file name',
    ContentType: 'image/*',
    Expires: 60 * 10, // Url is available for 10 mins
    Metadata: {
      'email': 'user@example.com',
      'custom-field': 'custom data',
    },
  };

  res.send(await s3.getSignedUrl('putObject', params));
});
  1. User uses the url to upload to S3.用户使用 url 上传到 S3。

More info:更多信息:

https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html . https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM