images.controllers.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /** logic for image routes */
  2. import multer from 'multer';
  3. import Image from "../models/image.model.js";
  4. import { v2 as cloudinary } from 'cloudinary';
  5. import dotenv from 'dotenv';
  6. import path from 'path';
  7. import DatauriParser from 'datauri/parser.js';
  8. dotenv.config();
  9. const dUri = new DatauriParser();
  10. const dataUri = req => dUri.format(path.extname(req.file.originalname).toString(), req.file.buffer);
  11. cloudinary.config({
  12. cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  13. api_key: process.env.CLOUDINARY_API_KEY,
  14. api_secret: process.env.CLOUDINARY_API_SECRET,
  15. });
  16. const storage = multer.memoryStorage();
  17. /*
  18. const imageFileFilter = (req, file, cb) => {
  19. console.log("File in filter", file);
  20. if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/jpg' || file.mimetype === 'image/png') {
  21. cb(null, true);
  22. } else {
  23. cb(null, false);
  24. }
  25. }*/
  26. export const upload = multer({
  27. storage: storage,
  28. limits: {
  29. // Allow upload files under 10MB
  30. fileSize: 10485760,
  31. },
  32. // fileFilter: imageFileFilter,
  33. });
  34. export const uploadSingleImage = async (req, res) => {
  35. const image = dataUri(req).content;
  36. const { category, categoryId, tags, name } = req.body;
  37. const folderName = category && categoryId ? category + '/' + categoryId : req.params.folder;
  38. const uploadOptions = {
  39. folder: folderName,
  40. tags: tags || [],
  41. };
  42. if (category === 'userProfile') {
  43. uploadOptions.folder = category;
  44. uploadOptions.public_id = categoryId;
  45. uploadOptions.overwrite = true;
  46. uploadOptions.transformation = { aspect_ratio: 1, gravity: "faces", crop: "fill" };
  47. }
  48. cloudinary.uploader.upload(image, uploadOptions).then((cloudinaryImage) => {
  49. // console.log('upload successful');
  50. const { public_id, secure_url, url } = cloudinaryImage;
  51. const newImage = new Image({
  52. categoryName: category,
  53. categoryId,
  54. url: secure_url || url,
  55. cloudinaryPublicId: public_id,
  56. name,
  57. });
  58. try {
  59. newImage.save().then(() => {
  60. // console.log('added image to ' + folderName, public_id, name);
  61. res.status(201).json({ 'message': 'successfully added new Image', 'Image': newImage })
  62. });
  63. } catch (error) {
  64. res.status(409).json({ message: error.message, errorDetails: 'upload successful, but database storage failed' });
  65. }
  66. }).catch((error) => {
  67. res.status(409).json({ message: error.message, errorDetails: 'upload failed' });
  68. });
  69. }
  70. async function copySingleImage(image, category, newId) {
  71. let returnImage = null;
  72. const folder = category + '/' + newId;
  73. if (image.url) {
  74. await cloudinary.uploader.upload(image.url, { folder: folder }).then(async (cloudinaryImage) => {
  75. // console.log('upload successful');
  76. const { public_id, secure_url, url } = cloudinaryImage;
  77. const newImage = new Image({
  78. categoryName: category,
  79. categoryId: newId,
  80. url: secure_url || url,
  81. cloudinaryPublicId: public_id,
  82. name: image.name,
  83. });
  84. await newImage.save().then((savedImage) => {
  85. returnImage = savedImage;
  86. }).catch((error) => {
  87. console.log('upload of copied image successful, but database storage failed', 'error:', error.message);
  88. });
  89. }).catch((error) => {
  90. console.log('image upload failed because ', error);
  91. });
  92. }
  93. return returnImage;
  94. }
  95. export const copyImagesForCategory = async (req, res) => {
  96. let { category, oldId, newId } = req.params;
  97. let newImages = [];
  98. await Image.find({ categoryName: category, categoryId: oldId }, async function (err, foundImages) {
  99. if (err) {
  100. console.log('error in find', err);
  101. } else {
  102. if (foundImages && foundImages.length > 0) {
  103. newImages = await Promise.all(foundImages.map(async (i) => {
  104. return await copySingleImage(i, 'mealImages', newId)
  105. }));
  106. if (newImages.length > 0) {
  107. res.status(201).json({ 'message': 'successfully copied Images', newImages });
  108. } else {
  109. res.status(400).json({ 'info': `copying images failed. Check log for more info` });
  110. }
  111. } else {
  112. res.status(200).json({ 'message': 'no images had to be copied' });
  113. }
  114. }
  115. });
  116. }
  117. export const deleteSingleImage = async (req, res) => {
  118. const image = req.body;
  119. Image.findByIdAndDelete(image._id, {}, function (err, deletionResult) {
  120. if (err) {
  121. res.status(400).json({ 'info': `Deletion of image ${image._id} failed`, 'message': err.message });
  122. } else {
  123. cloudinary.uploader.destroy(image.cloudinaryPublicId).then((result) => {
  124. res.status(201).json({ 'info': 'image deleted', deletionResult, cloudinaryResult: result });
  125. }).catch(error => {
  126. console.log('image deleted from database but not from cloudinary: ', image, 'reason', error);
  127. res.status(201).json({ 'info': 'image deleted from database but not from cloudinary', 'cloudinaryError': error });
  128. });
  129. }
  130. });
  131. }
  132. export const deleteAllImagesFromCategory = async (req, res) => {
  133. let category = req.params.category;
  134. let id = req.params.id;
  135. // console.log('delete all images from ', category, id);
  136. await Image.find({ categoryName: category, categoryId: id }, async function (err, foundImages) {
  137. if (err) {
  138. console.log('error in find', err);
  139. } else {
  140. await Promise.all(foundImages.map(async (i) => {
  141. await cloudinary.uploader.destroy(i.cloudinaryPublicId).catch(error => {
  142. console.log('deletion of ' + i.name + ' from cloudinary failed because', error);
  143. });
  144. }));
  145. const folder = category + '/' + id;
  146. cloudinary.api.delete_folder(folder).catch(err => {
  147. console.log('error on delete folder', err);
  148. }).finally(() => {
  149. Image.deleteMany({ categoryName: category, categoryId: id }, {}, function (err, deletionResult) {
  150. if (err) {
  151. res.status(400).json({ 'info': `Deletion of images from ${category} ${id} failed`, 'message': err.message });
  152. } else {
  153. res.status(201).json({ 'info': `images from ${category} with ${id} deleted`, deletionResult });
  154. }
  155. });
  156. });
  157. }
  158. });
  159. }
  160. export const deleteAllImagesFromCategoryInternally = async (category, categoryId) => {
  161. await Image.find({ categoryName: category, categoryId: categoryId }, async function (err, foundImages) {
  162. if (err) {
  163. console.log('error in find', err);
  164. } else {
  165. await Promise.all(foundImages.map(async (i) => {
  166. await cloudinary.uploader.destroy(i.cloudinaryPublicId).catch(error => {
  167. console.log('deletion of ' + i.name + ' from cloudinary failed because', error);
  168. });
  169. }));
  170. const folder = category + '/' + categoryId;
  171. console.log('trying to delete folder ' + folder);
  172. cloudinary.api.delete_folder(folder).catch(err => {
  173. console.log('error on delete folder', err);
  174. }).finally(() => {
  175. Image.deleteMany({ categoryName: category, categoryId: categoryId }, {}, function (err, deletionResult) {
  176. if (err) {
  177. console.log(`Deletion of images from ${category} ${categoryId} failed`, err.message);
  178. } else {
  179. console.log(deletionResult.n + ` images from ${category} with ${categoryId} deleted`);
  180. }
  181. });
  182. });
  183. }
  184. });
  185. }