From 8265a9efdf696a5a2c0c8d5d8ef6d6a82e646e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20No=C3=ABl?= Date: Mon, 28 Feb 2022 17:44:18 +0100 Subject: [PATCH] Fix the upload of files directly to an entity --- .../core/upload/server/services/upload.js | 63 +++++++++++------ packages/core/upload/tests/upload.test.e2e.js | 67 +++++++++++++++++++ 2 files changed, 109 insertions(+), 21 deletions(-) diff --git a/packages/core/upload/server/services/upload.js b/packages/core/upload/server/services/upload.js index 398a219663..bb4adca7de 100644 --- a/packages/core/upload/server/services/upload.js +++ b/packages/core/upload/server/services/upload.js @@ -45,6 +45,20 @@ const sendMediaMetrics = data => { } }; +const addTmpWorkingDirectory = async (files, providedTmpWorkingDirectory) => { + let tmpWorkingDirectory = providedTmpWorkingDirectory; + + if (!tmpWorkingDirectory) { + tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-upload-')); + } + + Array.isArray(files) + ? files.forEach(file => (file.tmpWorkingDirectory = tmpWorkingDirectory)) + : (files.tmpWorkingDirectory = tmpWorkingDirectory); + + return tmpWorkingDirectory; +}; + module.exports = ({ strapi }) => ({ async emitEvent(event, data) { const modelDef = strapi.getModel('plugin::upload.file'); @@ -118,10 +132,8 @@ module.exports = ({ strapi }) => ({ async upload({ data, files }, { user } = {}) { // create temporary folder to store files for stream manipulation - const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-upload-')); - Array.isArray(files) - ? files.forEach(f => (f.tmpWorkingDirectory = tmpWorkingDirectory)) - : (files.tmpWorkingDirectory = tmpWorkingDirectory); + const tmpWorkingDirectory = await addTmpWorkingDirectory(files); + let uploadedFiles = []; try { @@ -220,8 +232,8 @@ module.exports = ({ strapi }) => ({ } // create temporary folder to store files for stream manipulation - const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-upload-')); - file.tmpWorkingDirectory = tmpWorkingDirectory; + const tmpWorkingDirectory = await addTmpWorkingDirectory(file); + let fileData; try { @@ -359,22 +371,31 @@ module.exports = ({ strapi }) => ({ async uploadToEntity(params, files) { const { id, model, field } = params; - const arr = Array.isArray(files) ? files : [files]; - const enhancedFiles = await Promise.all( - arr.map(file => { - return this.enhanceFile( - file, - {}, - { - refId: id, - ref: model, - field, - } - ); - }) - ); + // create temporary folder to store files for stream manipulation + const tmpWorkingDirectory = await addTmpWorkingDirectory(files); - await Promise.all(enhancedFiles.map(file => this.uploadFileAndPersist(file))); + const arr = Array.isArray(files) ? files : [files]; + + try { + const enhancedFiles = await Promise.all( + arr.map(file => { + return this.enhanceFile( + file, + {}, + { + refId: id, + ref: model, + field, + } + ); + }) + ); + + await Promise.all(enhancedFiles.map(file => this.uploadFileAndPersist(file))); + } finally { + // delete temporary folder + await fse.remove(tmpWorkingDirectory); + } }, getSettings() { diff --git a/packages/core/upload/tests/upload.test.e2e.js b/packages/core/upload/tests/upload.test.e2e.js index 352e4d0539..6115fa38ee 100644 --- a/packages/core/upload/tests/upload.test.e2e.js +++ b/packages/core/upload/tests/upload.test.e2e.js @@ -4,20 +4,36 @@ const fs = require('fs'); const path = require('path'); // Helpers. +const { createTestBuilder } = require('../../../../test/helpers/builder'); const { createStrapiInstance } = require('../../../../test/helpers/strapi'); const { createAuthRequest } = require('../../../../test/helpers/request'); +const builder = createTestBuilder(); let strapi; let rq; +const dogModel = { + displayName: 'Dog', + singularName: 'dog', + pluralName: 'dogs', + kind: 'collectionType', + attributes: { + profilePicture: { + type: 'media', + }, + }, +}; + describe('Upload plugin end to end tests', () => { beforeAll(async () => { + await builder.addContentType(dogModel).build(); strapi = await createStrapiInstance(); rq = await createAuthRequest({ strapi }); }); afterAll(async () => { await strapi.destroy(); + await builder.cleanup(); }); describe('GET /upload/settings => Get settings for an environment', () => { @@ -162,6 +178,57 @@ describe('Upload plugin end to end tests', () => { }); }); + describe('POST /api/:uid => Create an entity with a file', () => { + test('With an image', async () => { + const res = await rq({ + method: 'POST', + url: '/api/dogs?populate=*', + formData: { + data: '{}', + 'files.profilePicture': fs.createReadStream(path.join(__dirname, 'rec.jpg')), + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + attributes: { + profilePicture: { + data: { + id: expect.anything(), + }, + }, + }, + id: expect.anything(), + }, + }); + }); + + test('With a pdf', async () => { + const res = await rq({ + method: 'POST', + url: '/api/dogs?populate=*', + formData: { + data: '{}', + 'files.profilePicture': fs.createReadStream(path.join(__dirname, 'rec.pdf')), + }, + }); + + expect(res.statusCode).toBe(200); + expect(res.body).toMatchObject({ + data: { + attributes: { + profilePicture: { + data: { + id: expect.anything(), + }, + }, + }, + id: expect.anything(), + }, + }); + }); + }); test.todo('GET /upload/files/:id => Find one file'); test.todo('GET /upload/search/:id => Search files'); test.todo('DELETE /upload/files/:id => Delete a file');