-
Notifications
You must be signed in to change notification settings - Fork 1
06. Uploading to Cloudinary
Nick Doiron edited this page Dec 6, 2017
·
2 revisions
There are cloud file systems, CDNs, etc where you can store files. There are also services which use these same services, but have an easier interface for coders. In this case, I've decided to use Cloudinary to make multiple sizes and shapes of photos available.
Set up a Cloudinary account, then install their Node module and a file POST helper, busboy:
npm install cloudinary async-busboy --save
Cloudinary comes with some different environment variables, set automatically on Heroku.
In a new uploads.js file, import the modules
// uploads.js
const cloudinary = require('cloudinary');
const asyncBusboy = require('async-busboy')
...
if (!process.env.CLOUDINARY_URL) {
// CLOUDINARY_URL is the method used automatically by Heroku
// if you're elsewhere, have these variables:
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
}// include enctype="multipart/form-data" whenever you are uploading files
// also include the CSRF variable directly in the action URL - it helps!
form(action="/upload?_csrf=" + csrfToken, method="POST", enctype="multipart/form-data")
input(type="file", name="upload")
input(type="submit", value="Upload")You should create an Image model to record any uploaded images and connect them to usernames
const mongoose = require('mongoose');
var imageSchema = mongoose.Schema({
user_id: String,
src: String
});
module.exports = mongoose.model('Image', imageSchema);Like you did for logins, pass the app and router to uploads.js
// app.js
const setupUploads = require('./uploads.js');
setupUploads(app, router);Back in uploads.js:
module.exports = function (app, router) {
router.post('/upload', async function (ctx) {
var requser = ctx.req.user;
if (!requser) {
// not logged in
return ctx.redirect('/login');
}
// use new syntax to receive multiple results from asyncBusboy
var {files, fields} = await asyncBusboy(ctx.req);
// only single file upload for now
if (files.length !== 1) {
return ctx.redirect('/profile');
}
var file = files[0];
// send to cloudinary, and wait for upload to finish before going back to profile
await cloudinary.uploader.upload(file.path, async function(result) {
// create record in MongoDB
var i = new Image({
user_id: requser.name,
src: result.public_id
});
await i.save();
}, { public_id: Math.random() + "_" + (new Date() * 1) } );
// see the new profile
ctx.redirect('/profile');
});
}