Score:0

How upload a file\image via json api?

br flag

I'm trying to upload a file or image on a D9 site via json api. The test is namely to upload the user picture on the user entity.

I've been following the documentation or read questions about, but I can't get it working.

The front-end is done with Next.js.

One the test done is the following:

The front-end next calls the next.js api server:

const filename = selectedFile.name;
const fr = new FileReader();
fr.readAsArrayBuffer(selectedFile);
fr.onload = async function () {
    const arrayBuffer = fr.result;
    if (arrayBuffer && typeof arrayBuffer !== 'string') {
        const base64String = _arrayBufferToBase64(arrayBuffer);
        const cookieSession = await getUpdateCookie();
        const res = await fetch(`/api/users-test/user?cookie=${cookieSession}&name=${filename}`, {
            method: 'POST', body: base64String,
        });
    }
}

function _arrayBufferToBase64(buffer: ArrayBuffer) {
    let binary = '';
    const bytes = new Uint8Array(buffer);
    const len = bytes.byteLength;
    for (let i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
    return window.btoa(binary);
}

The api next.js server post then to Drupal:

const res = await fetch(
      `${process.env.NEXT_PUBLIC_DRUPAL_BASE_URL}/jsonapi/user/user/{userID}/user_picture`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/octet-stream',
          Accept: 'application/vnd.api+json',
          'Content-Disposition': `name="file"; filename="${filename}"`,
          Authorization: `Bearer ${token}`,
        },
        body: req.body,
      }
    );

I tried different ways to convert the file to "binary file data", but none work: the user picture is always a blank square with an X.

However, if I try the same call with postman, the file is correctly loaded:

postman

So, for now, I hypothesize the problem is on the javascript code, while Drupal has been configured correctly.

id flag
If there is already a question then we should not need to ask it again.
Giuseppe avatar
br flag
@cilefen unfortunately, the code in that question did not work for me, otherwise I would have already had it working. For example, the passage via the api server Next is an extra layer that other answer do not cover.
cn flag
If it works with postman, but not with next.js, then this might be a better question on Stack Overflow, which probably has more people familiar with next.js.
Score:0
cn flag

I am currently having the same issue. The post goes thru perfectly in postman. the code snippet below is used to perform the post action in nextjs


//this function is used to convert the file

const readFileDataAsBase64 = (fl) => {
    const file = fl;

    return new Promise((resolve, reject) => {
        const reader = new FileReader();

        reader.onload = (event) => {
          console.log('here')
            resolve(event.target.result);
        };

        reader.onerror = (err) => {
            reject(err);
        };

        reader.readAsDataURL(file);
    });
}

//get the value of the file converted to binary
const filedata= await readFileDataAsBase64(values.files[0]);

//call the post file function to perform the post
const resfile = await postFiles(
      'http://the-url',
      filedata,
      values.files[0].name
    );

const postFiles = (url, body, filename) => {

    const myPost = async() => {
        try {
         const res = await fetch(url, {
              method: 'POST',
              body: body,
              headers: {
                'Content-Type': 'application/octet-stream',
                'Content-Disposition': `file; filename=${filename}`,
                'api-key': 'myapi-key',
              },
            });
        } catch (err){
        }
  
    } 
    postData();
  
  };

This file isn't being posted to drupal. Did anyone found a solution to properly post a file using the api

Giuseppe avatar
br flag
For now, I've found 2 points: 1. there was probably a CORS problem, so I had to configure it. See e.g. https://www.drupal.org/node/3024331#comment-13261556 2. There is some problem in the call between the "next front-end" and the "next server". If I post the image via a plain JS or directly from the "next front-end" it works, so the problem is most likely there.
msd026 avatar
cn flag
I solved the issue. The post wasn't working with fetch, but axios works fine.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.