0

I am using react dropzone on a page to send a file to an api route /api/upload and then use the api route to upload the file to a Strapi upload api like this:

import formidable from 'formidable';
var FormData = require('form-data');
const fs = require('fs');

export default async function handler(req, res) {
  const {cookies: {jwt}, query: {user_id}} = req
  
  if (req.method === 'POST') {

    const form = new formidable.IncomingForm();


    const submittedformdata = await new Promise((resolve, reject) => {
      form.parse(req, (err, fields, files) => {
        if (err) {
          reject(err);
        } else {
          resolve({ fields, files });
        }
      });
    });

    const { fields, files } = submittedformdata;

    if(Object.keys(fields).length){
      const resp = await fetch(`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/users/${user_id}`,{
        method: "PUT",
        headers: {
            Authorization: `Bearer ${jwt}`,
            "Content-Type": "application/json"
        },
        body: JSON.stringify(fields)
    })

    const data = await resp.json()

    console.log('Fields data',data);
    }

    if(files.files){
      console.log('There are files in there',`${process.env.NEXT_PUBLIC_API_URL}/upload`, req.headers["content-type"],);
      const fileStream = fs.createReadStream(files.files.filepath);

      const formData = new FormData();
      formData.append('files', fileStream, files.files.originalFilename);
      formData.append('ref', 'plugin::users-permissions.user')
      formData.append('refId', user_id)
      formData.append('field', 'profile_picture')


      const imageResp = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/upload`,{
        method: "POST",
        headers: {
            Authorization: `Bearer ${jwt}`
        },
        body: formData
    })

      const imageData = await imageResp.json()

      console.log('imageData',imageResp, imageData);
      
    }

    res.status(200).json({ fields, files });



  } else {
    res.status(405).json({ error: 'Method not allowed' });
  }
}

export const config = {
  api: {
    bodyParser: false,
  },
};

However Strapi keeping return an error message

{
  data: null,
  error: {
    status: 400,
    name: 'ValidationError',
    message: 'Files are empty',
    details: {}
  }
}

What could I be doing wrong? I have been at it for the past 2 weeks but no breakthrough

Gregoire Ducharme
  • 1,095
  • 12
  • 24
Kofi Talent
  • 145
  • 2
  • 12

1 Answers1

0

Hi I think you missconcepting the pipeline here.

api/upload route is the one you should use to upload files, files are uploaded via FormData, you receive an object with [{id}] of uploaded files

api/contentType/ route, expects this [{id}] to be provided with data

Example would be:

// note that i'm omitting error handling here

let formData = new FormData();
files.forEach(file => formData.append('files', file));

const { data:media } = await fetch('api/upload', { body: formData, method: 'POST', headers: ... }).then(res => res.json());


// user entry update 
const data = { 
    title: 'idk',
    media // < that is array of object with mandatory `id` prop 
 }

const entry = await fetch(`api/user/${userId}`, { method: 'PUT', body: JSON.stringify({...data}) }, headers: ... })

Note that for regular api routes you need to have body: { data } for user permissions body: {...data }

antokhio
  • 1,497
  • 2
  • 11
  • 16