-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathuploadCloudinary.js
125 lines (113 loc) · 4.12 KB
/
uploadCloudinary.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
////////////////////////////////
// Upload files to Cloudinary //
////////////////////////////////
const multer = require("multer");
const stream = require("stream");
const cloudinary = require("cloudinary");
const app = require("./index");
if (!process.env.CLOUDINARY_URL) {
console.error(
"*******************************************************************************"
);
console.error(
"*******************************************************************************\n"
);
console.error(
"You must set the CLOUDINARY_URL environment variable for Cloudinary to function\n"
);
console.error(
'\texport CLOUDINARY_URL="cloudinary:// get value from heroku"\n'
);
console.error(
"*******************************************************************************"
);
console.error(
"*******************************************************************************"
);
process.exit(1);
}
const doUpload = (publicId, req, res, next) => {
const uploadStream = cloudinary.uploader.upload_stream(
(result) => {
// capture the url and public_id and add to the request
req.fileurl = result.url;
req.fileid = result.public_id;
next();
},
{ public_id: req.body[publicId] }
);
// multer can save the file locally if we want
// instead of saving locally, we keep the file in memory
// multer provides req.file and within that is the byte buffer
// we create a passthrough stream to pipe the buffer
// to the uploadStream function for cloudinary.
const s = new stream.PassThrough();
s.end(req.file.buffer);
s.pipe(uploadStream);
s.on("end", uploadStream.end);
// and the end of the buffer we tell cloudinary to end the upload.
};
// multer parses multipart form data. Here we tell
// it to expect a single file upload named 'image'
// Read this function carefully so you understand
// what it is doing!
const uploadImage = (publicId) => (req, res, next) =>
multer().single("image")(req, res, () => doUpload(publicId, req, res, next));
///////////////////////////////////////////////////////////////////////////////
// These three functions are examples to validate that uploading works
// You do not want them in your final application
//
function postImage(req, res) {
// create an image tag from the cloudinary upload
const image = cloudinary.image(req.fileid, {
format: "png",
width: 100,
height: 130,
crop: "fill",
});
// create a response to the user's upload
res.send(
`Uploaded: ${req.fileurl}<br/><a href="${req.fileurl}">${image}</a>`
);
}
function uploadAvatar(req, res) {
res
.status(200)
.json({ message: "Avatar updated successfully", url: req.fileurl });
}
function setup(app) {
app.put("/avatar", uploadImage("avatar"), uploadAvatar);
}
function getImage(req, res) {
// This form has two parts: image and title
// the title is used as the name of the uploaded file
// if not supplied, then we get some default name from Cloudinary
// the image is the file to upload
// the name "image" must be the same as what we expect in the formData
// in the multer().single() middleware
res.send(
'<form method="post" enctype="multipart/form-data">' +
'<p>Public ID: <input type="text" name="title"/></p>' +
'<p>Image: <input type="file" name="image"/></p>' +
'<p><input type="submit" value="Upload"/></p>' +
"</form>"
);
}
function setup(app) {
// this provides a form. This is uneeded because
// we have the upload on the frontend already.
// but I provide it here for the inclass exercise example
app.get("/image", getImage);
// body-parser provides us the textual formData
// which is just title in this case
app.post("/image", uploadImage("title"), postImage);
}
// remove the above three functions and change the last line below to
// module.exports = uploadImage
//
// then to use in profile.js do (see comment in getImage about the string 'avatar')
// const uploadImage = require('./uploadCloudinary')
// app.put('/avatar', uploadImage('avatar'), uploadAvatar)
//
///////////////////////////////////////////////////////////////////////////////
module.exports = uploadImage;