0

I am trying to send a PDF file through multipart/form-data to Box.com's API. The PDF data is encoded in Base64. Since my module is being run through the GraalVM, which is setup in a way that node's built-in modules are blocked, I have to create the form-data payload from scratch.

The main issue that I am having is that the PDF keeps being stored as text and not being decoded back into a binary file.

Here's my code:

const testFile = file.load(321321654)

    const boundary = 'ikjbhciuydgwyigdchbwikcbjlikwudhqcviudgwvcihblh'

    const header = {
        'Content-Type': 'multipart/form-data; boundary=' + boundary,
        'Authorization': 'Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX'
    }

    const body = []
    body.push('--' + boundary)
    body.push('Content-Disposition: form-data; name="attributes"');
    body.push('')
    body.push(JSON.stringify({name: testFile.name, parent: { id: 12216548 }}))
    body.push('--' + boundary)
    body.push('Content-Disposition: form-data; name="testfile"' + '; filename="' + testFile.name + '"')
    body.push('content-type: application/pdf;charset=UTF-8')
    body.push('Content-Transfer-Encoding: BASE64')
    body.push('')
    body.push(testFile.getContents())
    body.push('--' + boundary + '--')
    body.push('')

    const result = https.post({
        url: 'https://upload.box.com/api/2.0/files/content',
        headers: header,
        body: body.join('\r\n')
    })

The results of the body.join is:

--ikjbhciuydgwyigdchbwikcbjlikwudhqcviudgwvcihblh
Content-Disposition: form-data; name="attributes"

{\"name\":\"Get Started with Box.pdf\",\"parent\":{\"id\":207753393458}}
--ikjbhciuydgwyigdchbwikcbjlikwudhqcviudgwvcihblh
Content-Disposition: form-data; name="file"; filename="Get Started with Box.pdf"
content-type: application/pdf;charset=UTF-8
Content-Transfer-Encoding: BASE64

JVBERi0xLjMKJcTl8uXrp/Og0MTGCjQgMCBvYmoKPDw (actual payload string shortened)
--ikjbhciuydgwyigdchbwikcbjlikwudhqcviudgwvcihblh--

Unfortunately, the file is loaded into box, but to decoded back to a PDF binary. It's just a text file of the Base64 string.

I have tried this with a local express server that I created and have a similar issue when using the Multer package to handle a multipart/form-data upload. Oddly, when I switch to the Formidable package it works just fine with my above code.

I've looked through the form-data specification and the payload I am building looks correct to me. The box.com forums have others asking a similar question to mine, but no one has provided an answer to any of those. A google search and stack overflow search hasn't turned up a similar question to mine.

Does anyone have any suggestions as to what may be happening?

  • what does *the file is loaded into box* mean? what box where? – Jaromanda X May 18 '23 at 00:41
  • I think OP means the file is loaded onto box.com's api – Justiniscoding May 18 '23 at 00:45
  • Yes, the file is transferred to box.com. It shows with the file name I gave, with the .pdf extension, but it’s not a valid pdf. It’s a text file of the base64 string. – Matthew Carter May 18 '23 at 00:58
  • you need to push all that stuff (like 'content-type: application/pdf;charset=UTF-8') to the header, not body – d.k May 18 '23 at 04:19
  • "*node's built-in modules are blocked*" Then what does `https` refer to? How does Node function at all without the built-ins? – esqew May 18 '23 at 14:03
  • @DmitryKoroliov The main header is Content-Type: multipart/form-data. Each part in the form multipart/form-data spec allows for a Content-Type listed with the part. In my case an application/pdf. Here's a link to the spec [link](https://datatracker.ietf.org/doc/html/rfc7578). – Matthew Carter May 18 '23 at 14:08
  • @esqew the https is part of the SuiteScript API for NetSuite. It's their exposure of sending an http request. Unfortunately, I can't import node's built in modules like fs, Buffer, and so on. – Matthew Carter May 18 '23 at 14:10
  • @KJ Sorry, the JVBERi0xLjMKJcTl8uXrp/Og0MTGCjQgMCBvYmoKPDw etc. is not the whole actual payload, I shortened it to display in the question, the 'etc.' part I added to indicate there is actually more the string than I listed. The actual payload is a Base64 encoded string of the binary data, which is normal per my understanding of sending data in a multipart/form-data. – Matthew Carter May 18 '23 at 14:13
  • @esqew In my case node is run through the GraalVM, which has two modes when using node and Java together. One version allows you to import AMD modules, but blocks importing built in modules to your own code. So, in the background node has the built in, I just can't pull them into my code directly. – Matthew Carter May 18 '23 at 14:17
  • 1
    @KJ Unfortunately, I'm trying to upload through Box.com's api and all they specify is that the data should be sent as multipart/form-data. I'm trying to figure out why my data is being interpreted differently. In box, it's not taking it as a PDF, but to a local API built in Expressjs, using the Formidable package, it stores fine as a PDF. With the exact same built payload. Everything looks right to me in the payload according to the form-data spec. – Matthew Carter May 18 '23 at 14:22

1 Answers1

0

It looks like you may have started with the code here

Notice that the content-transfer-encoding is base64 not BASE64. Header names are supposed to be case-insensitive but I've run into encoding name case sensitivity in the past. This could also account for why your code works on one target and not another.

bknights
  • 14,408
  • 2
  • 18
  • 31