Skip to main content
Code Review

Return to Question

Notice removed Draw attention by DasBeasto
Bounty Ended with Sᴀᴍ Onᴇᴌᴀ's answer chosen by DasBeasto
Tweeted twitter.com/StackCodeReview/status/1059505836215754763
update wording/grammar, punctuation
Source Link

I'm using Node/Express/Mongoose to accept a JSON file containing a list of product details. These products are looped through, the images are uploaded to AWS S3, and the product is either accepted or rejected depending on validation. In the end the accepted products are uploaded to Mongo via Mongoose and all are returned to provide info to the uploader. This is my first time with any of these frameworks so I'm looking to improve best practices and find potential points of failure.

If theresthere are other contextual files/code needed let me knowknow; this is all that seemed relevant.

I'm using Node/Express/Mongoose to accept a JSON file containing a list of product details. These products are looped through, the images are uploaded to AWS S3, and the product is either accepted or rejected depending on validation. In the end the accepted are uploaded to Mongo via Mongoose and all are returned to provide info to the uploader. This is my first time with any of these frameworks so I'm looking to improve best practices and find potential points of failure.

If theres other contextual files/code needed let me know this is all that seemed relevant.

I'm using Node/Express/Mongoose to accept a JSON file containing a list of product details. These products are looped through, the images are uploaded to AWS S3, and the product is either accepted or rejected depending on validation. In the end the accepted products are uploaded to Mongo via Mongoose and all are returned to provide info to the uploader. This is my first time with any of these frameworks so I'm looking to improve best practices and find potential points of failure.

If there are other contextual files/code needed let me know; this is all that seemed relevant.

Notice added Draw attention by DasBeasto
Bounty Started worth 50 reputation by DasBeasto
edited tags
Link
200_success
  • 145.5k
  • 22
  • 190
  • 478
Source Link
DasBeasto
  • 155
  • 1
  • 9

Upload .JSON product list to MongoDB and upload image to AWS S3

I'm using Node/Express/Mongoose to accept a JSON file containing a list of product details. These products are looped through, the images are uploaded to AWS S3, and the product is either accepted or rejected depending on validation. In the end the accepted are uploaded to Mongo via Mongoose and all are returned to provide info to the uploader. This is my first time with any of these frameworks so I'm looking to improve best practices and find potential points of failure.

ProductRoutes.js

const keys = require("../config/keys.js");
const mongoose = require("mongoose");
const requireLogin = require("../middlewares/requireLogin");
var validator = require("validator");
const fileUpload = require("express-fileupload");
var fs = require("fs");
const aws = require("aws-sdk");
const S3_BUCKET = keys.awsBucket;
var path = require("path");
var request = require("request");
aws.config.update({
 region: "us-east-2",
 accessKeyId: keys.awsAccessKey,
 secretAccessKey: keys.awsSecretKey
});
require("../models/Product");
const Product = mongoose.model("product");
function validate(value, type) {
 switch (type) {
 case "string":
 return value && !validator.isEmpty(value, { ignore_whitespace: true });
 case "url":
 return (
 value &&
 !validator.isURL(value, {
 protocols: ["https, http"],
 require_protocol: true
 })
 );
 default:
 return value && validator.isEmpty(value, { ignore_whitespace: true });
 }
 return value == null || value.length === 0;
}
function saveImage(url, key) {
 let ext = path.extname(url);
 let params = {
 Key: key + ext,
 Bucket: S3_BUCKET,
 ACL: "public-read"
 };
 return new Promise(function(resolve, reject) {
 request.get(url).on("response", function(response) {
 if (response.statusCode === 200) {
 params.ContentType = response.headers["content-type"];
 var s3 = new aws.S3({ params })
 .upload({ Body: response })
 .send(function(err, data) {
 resolve(data);
 });
 } else {
 // return false;
 reject(false);
 }
 });
 });
}
module.exports = app => {
 app.use(fileUpload());
 app.post("/product/addProduct", requireLogin, async (req, res) => {
 let products = req.files.file.data;
 try {
 products = JSON.parse(products);
 } catch (e) {
 return res
 .status(400)
 .json({ success: false, message: "Invalid JSON product feed" });
 }
 let accepted = [];
 let rejected = [];
 for (const product of products) {
 if (!validate(product.sku, "string")) {
 rejected.push(product);
 return;
 }
 if (!validate(product.image_url, "url")) {
 rejected.push(product);
 return;
 }
 try {
 let result = await saveImage(product.image_url, `${product.owner}/${product.sku}`);
 product.image_url = result.Location;
 } catch (err) {
 // catches errors both in fetch and response.json
 return res.status(400).json({
 success: false,
 message: "Could not upload image",
 error: err
 });
 }
 let upsertProduct = {
 updateOne: {
 filter: { sku: product.sku },
 update: product,
 upsert: true
 }
 };
 accepted.push(upsertProduct);
 }
 // now bulkWrite (note the use of 'Model.collection')
 Product.collection.bulkWrite(accepted, function(err, docs) {
 if (err) {
 return res.status(400).json({
 success: false,
 message: "Something went wrong, please try again"
 });
 } else {
 return res.status(200).json({
 success: true,
 message: "Company successfully created",
 accepted: { count: accepted.length, list: accepted },
 rejected: { count: rejected.length, rejected: rejected },
 affiliate: docs
 });
 }
 });
 });
 app.get("/product/fetchAffiliateProducts", requireLogin, (req, res) => {
 var affiliateId = req.query.affiliateId;
 Product.find({ owner: affiliateId }, function(err, products) {
 if (err) {
 return res.status(400).json({
 success: false,
 message: "Could not find the requested company's products"
 });
 } else {
 return res.status(200).json({
 success: true,
 message: "Products successfully found",
 products: products
 });
 }
 });
 });
};

Product.js (model):

const mongoose = require('mongoose');
const {Schema} = mongoose;
const productSchema = new Schema({
 
 sku: {type: String, unique: true, required: true},
 name: {type: String, required: true},
 owner: {type: String, required: true},
 image_url: {type: String, required: true}
});
mongoose.model('product', productSchema);

Sample input

[
 {
 "sku": "123",
 "name": "Test Product 1",
 "owner": "Test Company 1",
 "image_url": "https://exmaple.com/src/assets/product1.png"
 },
 {
 "sku": "456",
 "name": "Test Product 3",
 "owner": "Test Company 2",
 "image_url": "https://exmaple.com/src/assets/product2.png"
 },
 {
 "sku": "789",
 "name": "Test Product 3",
 "owner": "Test Company 3",
 "image_url": "https://exmaple.com/src/assets/product3.png"
 }
]

If theres other contextual files/code needed let me know this is all that seemed relevant.

default

AltStyle によって変換されたページ (->オリジナル) /