cancel
Showing results for 
Search instead for 
Did you mean: 

How to upload an image to Document Information Extraction from AppGyver?

MioYasuatke
Active Contributor

I'm using AppGyver trial account. What I'm trying to achieve with AppGyver is:

1. Take a picture of invoice

2. Upload it to Document Information Extraction

To upload an image to Document Information Extraction, I've written JavaScript code below.

I've tested the same code with Node.js and it worked fine.

const {url, imagePath, imageName, token} = inputs

try {
  const response = await fetch(imagePath)
  const blob = await response.blob()

  const formData = new FormData()
  formData.append('file', blob, imageName)

  const options = {
    clientId: "default",
    extraction: {
      "headerFields": ["senderName"],
      "lineItemFields": ["description"]
    },
    documentType: "invoice"
  };  
  formData.append('options', JSON.stringify(options))
  console.log('before sending request')
  const response2 = await fetch(url, {
    method: "POST",
    headers: {
      "Authorization": "Bearer " + token
    },
    body: formData
  })

  console.log('response: ', response2)
  const json = await response2.json()
  console.log('json: ', json)
  return {id: json.id}
  
} catch (error) {
  console.log(JSON.stringify(error))
  const errorObj = {
    code: "9",
    message: "something went wrong",
    rawError: error
  }
  return [1, errorObj]
}

When I run the app, the logic fails at below part and an exception is caught.

  const response2 = await fetch(url, {
    method: "POST",
    headers: {
      "Authorization": "Bearer " + token
    },
    body: formData
  })

However, the error object is empty (as I see it in the console) and I have no clue what went wrong.

MioYasuatke
Active Contributor
0 Kudos

If I change the the method from 'POST' to 'GET' and remove the body, the call is successful. So I can tell that the URL and token are properly set.

Accepted Solutions (1)

Accepted Solutions (1)

MioYasuatke
Active Contributor

Passing the following object to form data, instead of blob object solved the issue.

const {url, token, fileObj} = inputs

const formData = new FormData()
const fileData = {
  uri: fileObj.path,
  size: fileObj.size,
  type: "image/jpeg",
  name: fileObj.name
}
formData.append('file', fileData)

...

Answers (3)

Answers (3)

merituulimelkko
Product and Topic Expert
Product and Topic Expert

If you are uploading an image, I would recommend using the Upload Files flow function instead of a custom JavaScript solution. See documentation here: https://docs.appgyver.com/data/file-uploads

However if you do need to upload as multipart/form-data, please see this solution by this community edition user: https://forums.appgyver.com/t/uploading-file-to-directus-multipart-form-data/11271/2

MioYasuatke
Active Contributor
0 Kudos

Hi Merituuli,

Thank you for your quick response.

Actually I have followed the page you mentioned, but it still doesn't work.

https://forums.appgyver.com/t/uploading-file-to-directus-multipart-form-data/11271

If I don't append the file to formData or remove the body altogether, fetch is successful but error is returned from the API.

Conversely, if I add the file to formData, fetch fails and the exception is caught. So I suspect that something is wrong with the blob object set to the formData.

merituulimelkko
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hmm, yes, it does sound like there is something wrong with the blob Object, however, I don't unfortunately know enough about what it should be like to be able to help further – you were saying this works from node.js? That you are able to upload a file with this code from there?

MioYasuatke
Active Contributor
0 Kudos

Hi merituulimelkko,

Yes, the code blow is my Node.js app which is working. There are some differences from the AppGyver's code, but the basic structure is the same.

I've also replaced the imagePath in the AppGyver's code with the one used blow, but the result was the same: exception occurred at the fetch call.

import express from 'express'
import fetch, {File, FormData} from 'node-fetch'

const app = express()
const PORT = process.env.PORT || 8080

const imageUrl = 'https://templates.invoicehome.com/invoice-template-en-classic-white-750px.png'
const baseUrl = 'https://aiservices-trial-dox.cfapps.eu10.hana.ondemand.com/document-information-extraction/v1'

app.post('/job', async (req, res) => {   
    const response = await fetch(imageUrl)
    const blob = await response.blob()

    const formData = new FormData()
    formData.append('file', blob, 'invoice-template-en-classic-white-750px.png')
    
    const options = {
        clientId: 'default',
        extraction: {
            'headerFields': ['senderName'],
            'lineItemFields': ['description']
        },
        documentType: 'invoice'
    }   
    formData.append('options', JSON.stringify(options))

    const token = await getToken()
    const response2 = await fetch(baseUrl + '/document/jobs', {
        method: 'POST',
        headers: {
            'Authorization': 'Bearer ' + token,
        },
        body: formData
    })
    const json = await response2.json()
    res.send(json)

})

async function getToken () {
    const tokenUrl = 'https://xxxx.authentication.eu10.hana.ondemand.com/oauth/token'
    const clientId = 'xxxx'
    const clientsecret = 'xxxx'
    
    return new Promise(resolve=> {
        fetch(tokenUrl + '?grant_type=client_credentials', {
            method: 'GET',
            headers: {
                'Authorization': 'Basic ' + btoa(clientId + ':' + clientsecret),
            }
        })    
        .then(response => response.json())
        .then(data => {
            resolve(data.access_token)
        })
    })

}

app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
merituulimelkko
Product and Topic Expert
Product and Topic Expert

Hmm, alright. I'm afraid I don't have the ability or knowledge to help you further. I would recommend posting in the forum thread linked above to ask community edition users if some of them would know how to help you forward. Other than that, you could try using console.log to check all different parameters as they come into the crashing part that they are looking exactly right.

MioYasuatke
Active Contributor
0 Kudos

Hi merituulimelkko,

Thank you for your advice. I've posted the following question to AppGyver community.

https://forums.appgyver.com/t/fetch-call-fails-when-blob-is-attached-to-formdata/15631

I'll update here if a solution is found.

amritansh
Advisor
Advisor
0 Kudos

Hi merituulimelkko,

Is there a way we can use the Upload Files flow function to communicate with a BTP Destination? In my use case, I would want to create a Destination for the BTP service that allows file upload and upload the file without considering authentication flows.

Regards

AnjalyGeorge
Explorer
0 Kudos

amritanshvns Did you get any solution to refer the Uplaod URL from the BTP Destination.

Thanks,

Anjaly

ferreira-renan
Explorer
0 Kudos

Hi mio.fujita,

Did you achieve this funcionality via javascript?

Im trying using javascript, but happens some 'cors' problems. I found a extension for chrome, but, is not a perfect solution. Did you go throught this too?

Tks.

MioYasuatke
Active Contributor
0 Kudos

Hi renanaferreira,

Yes, I used JavaScript for writing the code above. I did not have cors issue.

ferreira-renan
Explorer
0 Kudos

Hi mio.fujita ,

Nice, whats your browser navigator? Did you need some extension to it works?

Gouthami
Newcomer
0 Kudos

Hi Mio,

I followed the same mentioned in the post but ended up with CORS issue. 
How can we call the Document information extraction url with token dynamically? Can we call it through our BTP destinations with a Create method enabled?
How to pass form data body in Create method?

0 Kudos

Hello mioyasutake

Did you find an easy way to extract text from images?

I'm looking to take pictures of documents and then extract the text.

Thank you
MioYasuatke
Active Contributor
0 Kudos

Hi lovekaisei,

A solution was found yesterday. See my answer.