I have a react App where users can post images. When a use posts an image, my SQL table get updated. The column imgSRC gets updated with the name of the file.
For example - mysite_1536290516498.jpg
How can the code below be modified to server images from AWS instead of destFile: ${root}/dist/posts/${filename}?
My server code to post an image and update database is:
const app = require('express').Router(),
db = require('../../../config/db'),
Post = require('../../../config/Post'),
User = require('../../../config/User'),
root = process.cwd(),
upload = require('multer')({
dest: `${root}/dist/temp/`,
}),
{ ProcessImage, DeleteAllOfFolder } = require('handy-image-processor')
// POST [REQ = DESC, FILTER, LOCATION, TYPE, GROUP, IMAGE(FILE) ]
app.post('/post-it', upload.single('image'), async (req, res) => {
try {
let { id } = req.session,
{ desc, filter, location, type, group } = req.body,
filename = `mysite_${new Date().getTime()}.jpg`,
obj = {
srcFile: req.file.path,
destFile: `${root}/dist/posts/${filename}`,
},
insert = {
user: id,
description: desc,
imgSrc: filename,
filter,
location,
type,
group_id: group,
post_time: new Date().getTime(),
}
await ProcessImage(obj)
DeleteAllOfFolder(`${root}/dist/temp/`)
let { insertId } = await db.query('INSERT INTO posts SET ?', insert),
fullname = await User.getWhat('fullname', id)
await db.toHashtag(desc, id, insertId)
await User.mentionUsers(desc, id, insertId, 'post')
res.json({
success: true,
mssg: 'Posted!!',
post_id: insertId,
fullname,
filename,
})
} catch (error) {
db.catchError(error, res)
}
})
You do this using your Http server where you have access to .htaccess file or httpd.conf file in apache http server.
Just redirect all request for /dist/posts/ to AWS Path.
Before this you need to make sure you have same directory structure in AWs S3 bucket.
So when request comes from client for /dist/posts/image it will go to
http://aws/dist/posts/
This is also known as CDN if you google.
Related
Im using next.js and Stripe webhooks to insert checkout sessions to Supabase that will create a customer's order history. I'm able to get the information about the whole order written to a table called 'orders', but am wondering what the best way to add individual items within each checkout session to another table called 'order_items' is. This way I can map through main orders and then the children items. Appreciate any help provided. Here is what I have for getting orders associated with a customer:
const upsertOrderRecord = async (session: Stripe.Checkout.Session, customerId: string) => {
const { data: customerData, error: noCustomerError } = await supabaseAdmin
.from<Customer>('customers')
.select('id')
.eq('stripe_customer_id', customerId)
.single();
if (noCustomerError) throw noCustomerError;
const { id: uuid } = customerData || {};
const sessionData: Session = {
id: session.id,
amount_total: session.amount_total ?? undefined,
user_id: uuid ?? undefined
};
const { error } = await supabaseAdmin.from<Session>('orders').insert([sessionData], { upsert: true });
if (error) throw error;
console.log(`Product inserted/updated: ${session.id}`);
};
The Checkout Session object contains a line_items field which is a list of each item included in the purchase.
However this field is not included in the object by default, and therefore won't be a part of your webhook payload. Instead you'll need to make an API call in your webhook handle to retrieve the Checkout Session object, passing the expand parameter to include the line_items field:
const session = await stripe.checkout.sessions.retrieve('cs_test_xxx', {
expand: ['line_items']
});
I am having trouble getting my express server to attach a cookie on login. Bellow is the code I have written, I recently deployed my react app on Vercel which is what is making requests to my express server which I am still running locally. Everything works as it should and cookies are attaches when I run the react app locally.
Thank you,
Express Server
router.post("/", (req, res) =>{
const email = req.body.userName.toLowerCase()
const pass = req.body.password
db.query(`SELECT * FROM users WHERE email = '${email}'`, async (err, result) => {
if(result.rows.length === 1){
let user = result.rows[0]
bcrypt.compare(pass, user.password, (err, result) => {
if (err) throw err;
if(result === true){
user.password = 'blocked'
let token = jwt.sign({"tokenInfo": user, "userType": user.user_type}, secret, { algorithm: 'HS256'})
return res.cookie('userId', token, {
maxAge: 60000 * 60 * 2,
httpOnly: false
}).send({'message': "User Loged In", 'userType': user.user_type, 'userID': user.apaid})
} else {
return res.send({'message': 'Invalid Password', 'userType': 'false'})
}
})
} else if(result.rows.length > 1) {
res.send('WTF')
} else {
res.send({'message': 'Invalid User Name', 'userType': 'false'})
}
console.log(res.cookies)
})
})
Frontend and backend parts of your app should be served on the same domain in order to use cookies. If you created your app with create-react-app you can set up a proxy in your package.json file of your react app.
"devDependencies": {
...
},
"proxy": "http://*address of your locally running server eg:localhost:5000/*"
I uploaded an image file using axios post method and it was successfully uploaded to the server...
On return to the POST method, it returned the Image URL as:
{imageUrl: "/root/TTAppJava/images/players/Screenshot from 2020-11-24 16-38-57.png"}
Now, I want to display the image onto my screen.
How can I get that image?
I am using React.js to implement this.
The URL I used to post the image is:
http://139.59.16.180:8269/player/details/${id}
I am doing this to upload my data:
var formData = new FormData()
formData.append("file", image);
const theWrapper = {
"data": {
"name": name,
"age": age,
"email": email,
"gender": gender
}
}
formData.append("theWrapper", JSON.stringify(theWrapper))
Axios.post("http://139.59.16.180:8269/player/add",
formData,
{ headers: { Authorization: "Bearer " + localStorage.getItem("token") } }
).then(res => {
console.log(res)
alert("Player added successfully.")
history.push("/players")
})
.catch(err => alert(err.messge))
And the response I am getting is:
{id: 14, name: "shreyas", email: "asdfjka#gmail.com", gender: "Male", imageUrl: "/root/TTAppJava/images/players/Screenshot from 2020-11-24 16-38-57.png", …}
I will give you an example how its done in Node app, since the underlying concept will be the same as I am not a Java developer.
First please note your image_url/download_url should be saved as follows,
https://yourdomain/folder/image_name
example: http://localhost:3000/uploads_folder/my_image_name.jpg
and then you need a route in Java Spring which figures out what image to send to the front-end as Stream like below,
router.get("/:folder/:image_name", async (req, res) => {
const { folder, image_name } = req.params;
// find an image based on the downloadUrl in the folder where files are saved.
// Please note, after uploading file successfully generate a download url
// appropriately so that this route can help figure out which image you
// are looking for.
const file = path.join(`path/to/${folder}`, `${image_name}`);
// Figure out a way how stream works in your context.
// Providing MIME type is important!
const type = mime[path.extname(file).slice(1)] || "image/jpg";
const s = fs.createReadStream(file);
s.on("open", () => {
res.set("Content-Type", type);
s.pipe(res);
});
s.on("error", (err) => {
// Handle Error
});
});
I'm getting an unexpected 403 with trying to upload a file to S3. The weird part is that I have accomplished this before when I did this using the Java AWS SDK to generate the presigned url. I am now using the Python AWS SDK to generate the presigned url and I feel like I am doing the exact same thing.
Here is my code that WORKS no problem:
public UploadSignedRequest getUploadSignedRequest() {
AmazonS3 s3Client = getS3Client();
// Set the pre-signed URL to expire after one hour.
Date expiration = DateUtil.getSignedUrlExpirationDate();
// Generate the pre-signed URL.
String objectKey = UUID.randomUUID().toString();
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(BUCKET_NAME, objectKey)
.withMethod(HttpMethod.PUT)
.withExpiration(expiration);
String s3FilePath = String.format("%s/%s/%s", S3_URL, BUCKET_NAME, objectKey);
URL signedRequest = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
return new UploadSignedRequest(signedRequest, s3FilePath, objectKey);
}
Here is the successful client code:
var config = {
onUploadProgress: function (progressEvent) {
var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
updateProgressFunc(percentCompleted);
}
};
axios
.put(signedRequest.signedRequestUrl, videoFile, config)
.then(res => {
console.log(res);
console.log(res.status);
// save video metadata in db
dispatch(saveVideoMetadata(video));
})
.catch(function (error) {
console.log(error);
});
Now, here is me trying to accomplish essentially the same thing (image files instead of video files) using the Python AWS SDK.
def getS3UploadRequest(uuid):
return S3.generate_presigned_url(
ClientMethod='put_object',
Params={
'Bucket': BUCKET,
'Key': uuid
}
)
client code where I get the 403:
axios
.put(signedRequest, attachedFile)
.then(res => {
console.log("successfully uploaded file to s3");
console.log(res);
// dispatch(createProjectTaskComment(newComment, projectTaskId, userId, isFreelancer));
});
When I try to use the presignedUrl in postman, I get the following response back:
?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request
signature we calculated does not match the signature you provided.
Check your key and signing method.</Message>
<AWSAccessKeyId>gibberish</AWSAccessKeyId><StringToSign>PUT
Thanks for the help!!!
I am integrating CKEDITOR in react project and I am using AWS S3 bucket to upload the image that i add in text-editor.. Upload is working fine... The problem is if I delete the image in text-editor.It does not delete it from the AWS bucket.
Causing a lot of unwanted images in bucket. Hence , I need to delete the image from AWS server if it's not present in the text-editor..
How Can I do it??
I have the link to the image in the React Part as the repsonse of the upload.
You need to have a bucket name and key of that file in order to delete that file form AWS s3
const deleteS3Object = async (key, BUCKET_NAME) => {
return new Promise((resolve, reject) => {
try {
let s3bucket = new AWS.S3({
accessKeyId: IAM_USER_KEY,
secretAccessKey: IAM_USER_SECRET,
Bucket: BUCKET_NAME,
});
var params = { Bucket: BUCKET_NAME, Key: key };
s3bucket.deleteObject(params, function(err, data) {
if (err) reject(err);
// an error occurred
else resolve(data); // successful response
});
} catch (e) {
reject(e);
}
});
};