Jump to content
  • 0

Insert from URL - Document uploaden


Samsup

Question

Beste Filemakeraars, 

Voor het verzenden via Fedex probeer ik het uploaden van douanedocumenten te automatiseren.  Nu heeft Fedex daar een API voor, aanspreekbaar via JSON, en dit gaat tot zover allemaal goed, echter, krijg ik in filemaker het niet voor elkaar om het document te uploaden.  De API wordt aangesproken met form data,  en er is dus een stuk met daarin de shipment data in JSON ( metadata vooral), en een stuk form data waarin het PDF bestand mee moet.  In postman lukt het om een 200 OK reactie van de API terug te krijgen, maar als ik het in filemaker probeer krijg ik een bad request 400 error,  dus mijn vermoeden is dat ik iets in de syntax/curl niet goed doe bij de insert from URL scriptstap, maar ik heb inmiddels alle mogelijke variaties geprobeerd en krijg het niet goed, dus mijn hoop is dat er iemand een idee heeft wat er mis gaat.. 

Ter illustratie: Dit is wat postman doet ( de form data die postman mij weergeeft: 

curl --location 'https://documentapitest.prod.fedex.com/sandbox/documents/v1/etds/upload' \
--header 'Authorization: Bearer HIER_IS_OAUTH_TOKEN ' \
--form 'attachment=@"MiuVy_N2j/2307 8311.pdf"' \
--form 'document="{\"carrierCode\":\"FDXE\",\"contentType\":\"application/pdf\",\"meta\":{\"destinationCountryCode\":\"US\",\"originCountryCode\":\"NL\",\"shipDocumentType\":\"COMMERCIAL_INVOICE\",\"shipmentDate\":\"2023-08-17T14:08:41\",\"trackingNumber\":\"794791292805\"},\"name\":\"2307 8311.pdf\",\"workflowName\":\"ETDPostshipment\"}"' \
--form 'name="2307 8307.pdf"'

In filemaker heb ik een container aangemaakt met daarin het gewenste PDF bestand, deze wordt scriptmatig via een globale variabele toegevoegd aan de curl. 

De document metadata in JSon wordt ook in een script aangemaakt en toegevoegd,  de form name wordt ter plekke aangemaakt in de curl.  Deze Json werkt als ik deze vanuit filemaker dataviewer direct copy-paste in postman, dus dit stuk is -denk ik- goed. 

De curl ziet er als volgt uit:

"
-X POST
--header \"Authorization: Bearer " & $bearertoken & "\"
--header \"Content-Type: multipart/form-data\"
--form \"attachment=" & $$uploadfile & "\"
--form \"name=" & Invoices::_INVOICE ID MATCH FIELD & ".pdf\"
--form \"document="& $Jsoncurl & "\" 
-D $header"

 

De foutmelding die terugkomt is: 

{    "path": "/document/v1/etds/upload",    "customerTransactionId": "",    "error": "Bad Request",    "message": "Required request part 'attachment' is not present",    "timestamp": "2023-08-17T12:27:16.290+0000",    "status": "400"}

In de dataviewer is de $$uploadfile variable echter wel gevuld met de gewenste PDF, maar hij lijkt niet mee te komen. 

De curl heb ik overigens uit Postman genomen en deze door de curlparser van soliant heen gehaald https://www.soliantconsulting.com/blog/translating-auto-generated-curl-to-filemaker-curl/

 

 

Link to comment

22 answers to this question

Recommended Posts

  • 0
17 minuten geleden, Banach zei:

Wat staat er precies in de variabele $$uploadfile ? Is dat de serialized inhoud van de pdf of is dat @naam-van-pdf?

Letterlijk de scriptstap: Set variable $$uploadfile; value: invoicecontainerfield. 

 

Dus eerlijk gezegd weet ik niet of dit dan serialized is, en hoe ik dat zou kunnen doen? 

In de dataviewer geeft de variabele inderdaadwel aleen de naam van de pdf weer zonder inhoud, maar heb elders begrepen dat de dataviewer de inhoud van containers niet weer kan geven

Link to comment
  • 0
2 uren geleden, Banach zei:

Wat je kunt doen is het pdf bestand eerst exporteren naar b.v. het temp directory en dan --form \"attachment=@" & <pad-naar-pdf-in-tmp-dir> & "\" gebruiken.

Ik zal het eens proberen met een temp path, kijken of dat lukt is een goeie suggestie die ik nog niet heb geprobeerd, en niet eens aan heb gedacht.

 

Ik heb begrepen dat het niet mogelijk zou zijn om een bestand direct aan te spreken vanuit filemaker.  Maar misschien dat dit niet valt onder bestanden openen in filemaker..

 

op de filemaker helppagina schrijven ze het onderstaande, daarom ging ik ervanuit dat het via een container/variable moest gaan: 

 

Quote

 

Using variables

Although none of the supported options allow you to directly access or create files in the file system, you can specify a FileMaker variable as the source or destination of the data that the option requires. To access or create a file, you can set the variable to a container field.

To access a file, you can set the variable to a container field, which contains the file, then use that variable as the parameter of the cURL option.

 

 

en hier op het engelstalige forum wordt deze suggestie ook gewekt: 

https://community.claris.com/en/s/question/0D50H00006jI2OFSA0/how-do-i-to-upload-file-via-curl-from-filemaker

 

 

Link to comment
  • 0

Ik kan inmiddels bevestigen dat het gebruiken van het directe path naar het bestand dezelfde error 400," attachment not present" geeft.  

path in het variabele waarmee ik heb getest ziet er als volgt uit, bestand is daar uiteraard ook aanwezig; 

/C:/Users/user1/AppData/Local/Temp/S10.1/2307 8311.pdf  

Misschien dat daar nog wat aan geschaafd moet worden, bijvoorbeeld de /  voor het C:/  vertrouw ik niet helemaal, maar dat is nou eenmaal wat get(Temporarypath)  me geeft dus mag er dan toch vanuit gaan dat dat correct is? 

 

Link to comment
  • 0
3 minuten geleden, Banach zei:

Vergeet het apestaartje niet.

(Uiteraard is get(Temporarypath) correct. )

Is de @  niet om de variable te escapen uit de quotes?  

Ik heb daar om 1 of andere redenen wisselende ervaringen mee dus ik haal mijn variabelen altijd uit quotes door

"text in quotes" & $variabele & "nog meer text in quotes" 

 om 1 of andere reden heb ik hier altijd minder problemen mee, ook al ziet het er niet uit.  

Als er een andere redenen is om @ te gebruiken dan ken ik deze niet,  kan er ook niks over vinden als ik google op het gebruik van @ in filemaker scripts..  

 

Link to comment
  • 0
15 minuten geleden, Banach zei:

Het apestaartje heeft niets met Filemaker te maken maar alles met curl. Die moet weten waar het bestand te vinden is. Zie ook de betreffemde regel in Postman.

Nee, escapen doe je met de backslash.

Het was me in postman niet opgevallen moet ik eerlijk zeggen,  ik zie het nu ook staan

Dan zou de curl er zo uit moeten zien 

"--form \"attachment=@" & $$uploadfilepath & "\"

waarbij $$uploadfilepath  dan /C:/bestandpad/bestand.pdf  is  

Heb dit geprobeerd maar zelfde error, attachement not present.

Heb het ook geprobeerd met in plaats van het bestandpad de container met de pdf erin , zowel direct als via een variable, werkt ook niet ( met de @ )  

Ik doe dus nog iets verkeerd

na nog eens goed te kijken naar de curl parser tool van soliant (waarmee ik dus de postman curl data omzet naar wat volgens soliant correct is voor filemaker) , valt me op dat in hun suggestie de variable helemala niet ge-escaped wordt, kan dat kloppen?  Want dan kan ik de curl een stuk minder rommelig maken, en wellicht minder foutgevoelig / lost mijn probleem zich vanzelf op.. 

"--location --header \"Authorization: Bearer token\" 
--form attachment=@$your_file 

--form \"document=\"{\\"carrierCode\\":\\"FDXE\\",\\"contentType\\":\\"application/pdf\\",\\"meta\\":{\\"destinationCountryCode\\":\\"US\\",\\"originCountryCode\\":\\"NL\\",\\"shipDocumentType\\":\\"COMMERCIAL_INVOICE\\",\\"shipmentDate\\":\\"2023-08-17T14:08:41\\",\\"trackingNumber\\":\\"794791292805\\"},\\"name\\":\\"2307 8311.pdf\\",\\"workflowName\\":\\"ETDPostshipment\\"}\"\" --form \"name=\"2307 8307.pdf\"\" 
-D $header"

 

Link to comment
  • 0

Ik kan niet zoveel zinnigs zeggen over het document dat je wilt uploaden, want ik heb geen fedex koppelingen actief, maar het 'manual' escapen van quotes vind ik nooit een goed idee. Zoals je hierboven in je eigen post ziet, wordt dat snel complex en dit is ook vaak een goed recept voor fouten waar je heel lang naar kan zoeken.

De handigste manier is de functie Quote() te gebruiken, die neemt het escapen van quotes én backslashes voor zijn rekening. In dit geval maak je een JSON met daarin quotes die je moet escapen, dat zou je dan op de volgende manier kunnen doen:

List ( 
"--location" ; 
"--header " & Quote ( "Authorization: Bearer token" ) ; 
"--form attachment=@$your_file" ; 
"--form " & Quote ( "document=" & Quote ( 
	JSONSetElement ( "" ; 
		[ "carrierCode" ; "FDXE" ; 1 ] ; 
		[ "contentType" ; "application/pdf" ; 1 ] ; 
		[ "meta.destinationCountryCode" ; "US" ; 1 ] ; 
		[ "meta.originCountryCode" ; "NL" ; 1 ] ; 
		[ "meta.shipDocumentType" ; "COMMERCIAL_INVOICE" ; 1 ] ; 
		[ "meta.shipmentDate" ; "2023-08-17T14:08:41" ; 1 ] ; 
		[ "meta.trackingNumber" ; "794791292805" ; 1 ] ; 
		[ "name" ; "2307 8311.pdf" ; 1 ] ; 
		[ "workflowName" ; "ETDPostshipment" ; 1 ] ) ) ) ; 
"-D $header" 
)

en het resultaat hiervan gebruiken in cUrlOptions. Het resultaat ziet er als volgt uit:

--location
--header "Authorization: Bearer token"
--form attachment=@$your_file
--form "document=\"{\\\"carrierCode\\\":\\\"FDXE\\\",\\\"contentType\\\":\\\"application/pdf\\\",\\\"meta\\\":{\\\"destinationCountryCode\\\":\\\"US\\\",\\\"originCountryCode\\\":\\\"NL\\\",\\\"shipDocumentType\\\":\\\"COMMERCIAL_INVOICE\\\",\\\"shipmentDate\\\":\\\"2023-08-17T14:08:41\\\",\\\"trackingNumber\\\":\\\"794791292805\\\"},\\\"name\\\":\\\"2307 8311.pdf\\\",\\\"workflowName\\\":\\\"ETDPostshipment\\\"}\""
-D $header

De List()-functie introduceert returns (¶), maar FileMaker zet die bij gebruik in IFU keurig om in spaties. Je code wordt op deze manier leesbaarder, gemakkelijker te debuggen en je voorkomt fouten met quoten.

Link to comment
  • 0

zat inderdaad een spatie in de bestandsnaam. Die heb ik voor het gemak er even uitgebonjourd, maar ook het pad nog in quotes gezet voor de zekerheid

nu is de bestandsnaam gewoon invoice.pdf, Heb de variable $$uploadfilepath gemaakt met de functie: Quote(get(temporarypath)&$filename), dat geeft in de dataviewer dan de volgedende: "/C:/Users/user1/AppData/Local/Temp/S10.1/invoice.pdf"  -  waar het bestand dus ook fysiek staat, heb ik gecheckt)  dus voor de zekerheid alsnog in quotes

Dit staat dan in de curl: 

"
-X POST
--header \"Authorization: Bearer " & $bearertoken & "\"
--header \"Content-Type: multipart/form-data\"
--form \"attachment=@"& $$uploadfilepath & "\"
--form \"name=" & Invoices::_INVOICE ID MATCH FIELD & ".pdf\"
--form \"document="& $Jsoncurl & "\" 
-D $header"

en de error blijft attachment not present :D  

heb het ook geprobeerd met een variable van de container en de container direct, maar zelfde resultaat. 

 

Link to comment
  • 0

Dank menno voor de uitgebreide suggestie.  

omdat ik de JSON in een aparte variabele aanmaak ( en deze werkt ( denk ik) naar behoren, als deze namelijk verkeerd is, krijg ik direct een andere foutmelding), heb ik het als volgt gemaakt

List ( 
"--location" ; 
"--header " & Quote ( "Authorization: Bearer token" ) ; 
"--form attachment=@$$uploadfilelocation" ; 
"--form \"document=" & Quote ( $Json) ;
"-D $header" 
)

De authorisatie en document Json gaan zo te zien gewoon goed. Ik krijg wel weer de 400, attachment not found (snik) 

Ik blijf denk ik toch maar mijn variabelen gewoon buiten quotes gebruiken, want bijvoorbeeld  "--form attachment=@$$uploadfilepath" ;   geeft mij: 

--form attachment=@$$uploadfilepath   als resultaat in de dataviewer hij neemt de text dus letterlijk, in plaats van de variable in te pluggen.  

Dus uiteindelijk blijf ik mijn variabelen dan toch maar op de "lelijke" manier omzeilen door "-form attachment=@"& $$uploadfilepath ;  te doen.. 

dat geeft me dan wel weer --form attachment=@/C:/Users/user1/AppData/Local/Temp/S10.1/invoice.pdf , met de bekende error 400, attachment not present; dezelfde error als wanneer ik "--form attachment=@$$uploadfilepath"  gebruik besef ik nu  Dus er kan in plaats van dit path een willekeurige onzintext staan,  die error blijft komen. 

Conclusie is dan dat de quotes missen zoals banach al aangaf;

36 minuten geleden, Banach zei:

Probeer Qoute ($$uploadfilepath), zoals Menno het gebruik van qoutes ook aangeeft.

Ik heb het tevens geprobeerd met

"--form attachment=@"& Quote($$uploadfilepath) ; dat ziet er in de dataviewer dan als volgt uit, en dit lijkt me toch wel het correcte resultaat?

-X POST
--location
--header "Authorization: Bearer ingekortetoken"
--form attachment=@"/C:/Users/user1/AppData/Local/Temp/S10.1/invoice.pdf"
--form "{\"carrierCode\":\"FDXE\",\"contentType\":\"application/pdf\",\"meta\":{\"destinationCountryCode\":\"NL\",\"originCountryCode\":\"NL\",\"shipDocumentType\":\"COMMERCIAL_INVOICE\",\"shipmentDate\":\"2023-08-18T21:23:59\",\"trackingNumber\":\"794791292805\"},\"name\":\"invoice.pdf\",\"workflowName\":\"ETDPostshipment\"}"
-D $header

Maar, als ik dit doe krijg ik een 500 error   "Failed to parse multipart servlet request; nested exception is javax.servlet.ServletException: org.apache.tomcat.util.http.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is text/xml; charset=utf-8

Het is vooruitgang, want een andere error.  

Ik weet niet zeker of ik het goed lees, maar zegt deze error me nu dat de content type header text is?  Dat zou dan betekenen dat de json  dan toch niet goed werkt? Daar wordt het contenttype in vastgesteld namelijk.  

Ik zal het ook nog eens proberen met de Json portie buiten quotes zoals ik het eerst had, kijken wat dat doet. 

 

Link to comment
  • 0

Ik zag dat ik het nog niet helemaal zoals Menno had ingericht.

Ik heb nu gedaan: 

List ( 
"--location" ; 
"--header " & Quote ( "Authorization: Bearer " & $bearertoken ) ; 
"--form " & Quote("attachment=@"& $$uploadfilepath) ; 
"--form " & Quote("document=" & $Jsoncurl) ;
"--form " & Quote("name="& $filename);
"-D $header" 
)

geeft resultaat: 

--location
--header "Authorization: Bearer token"
--form "attachment=@\"/C:/Users/user1/AppData/Local/Temp/S10.1/invoice.pdf\""
--form "document={\"carrierCode\":\"FDXE\",\"contentType\":\"application/pdf\",\"meta\":{\"destinationCountryCode\":\"NL\",\"originCountryCode\":\"NL\",\"shipDocumentType\":\"COMMERCIAL_INVOICE\",\"shipmentDate\":\"2023-08-18T22:10:40\",\"trackingNumber\":\"794791292805\"},\"name\":\"invoice.pdf\",\"workflowName\":\"ETDPostshipment\"}"
--form "name=invoice.pdf"
-D $header

Ik denk dat het wel iets is met de quotes. 

Postman geeft namelijk dit: 

--form 'attachment=@"MiuVy_N2j/2307 8311.pdf"'
 
Het nare is dat daar enkele en dubbele quotes zitten, maar in filemaker gebruik ik alleen dubbele quotes.  De vraag is dus of het in Quote( "attachment=@" & $filelocatie)  dan wel de juiste soort quotes oplevert?? 
Ik heb ook geprobeert  "--form " & Quote("attachment=@"& Quote($$uploadfilepath)) ;
Dit geeft me dan  --form "attachment=@\"/C:/Users/Simon/AppData/Local/Temp/S10.1/invoice.pdf\"" als resultaat. maar tevens de error attachment not present nog steeds. 
 
Link to comment
  • 0

Ik heb even in de handleiding van fedex gekeken. Je mist de content-type in de header:

"--header “ & quote ("Content-Type: multipart/form-data“)

verder heb ik ook even gekeken in de handleiding van FileMaker en daarin staat beschreven hoe een bestand in een form moet worden ge-uploaded.

1) zet het bestand vanuit een containerveld met set-variable in $attachment

2) zet de attachment in de form op dezelfde manier als de payload in een requestbody:

”--form " & quote( “attachment=@$attachment”)

Zie hier ook dat er in de quote gewoon platte tekst staat en geen variable in een calculatie, dit is de manier waarop fmp werkt. https://help.claris.com/nl/pro-help/content/curl-options.html?Highlight=curl options#tn4

Link to comment
  • 0
18 uren geleden, menno zei:

Ik heb even in de handleiding van fedex gekeken. Je mist de content-type in de header:

"--header “ & quote ("Content-Type: multipart/form-data“)

verder heb ik ook even gekeken in de handleiding van FileMaker en daarin staat beschreven hoe een bestand in een form moet worden ge-uploaded.

1) zet het bestand vanuit een containerveld met set-variable in $attachment

2) zet de attachment in de form op dezelfde manier als de payload in een requestbody:

”--form " & quote( “attachment=@$attachment”)

Zie hier ook dat er in de quote gewoon platte tekst staat en geen variable in een calculatie, dit is de manier waarop fmp werkt. https://help.claris.com/nl/pro-help/content/curl-options.html?Highlight=curl options#tn4

WAt betreft de attachment in een containerveld en als variable: Klopt, daarom had ik dat in de eerste instantie zo geprobeerd, volgens de handleiding, kreeg dat niet werkend, kreeg hier advies om voor het bestandpad te gaan :D

 De headertype was ik inderdaad vergeten nadat ik je list suggestie probeerde te gebruiken, heb deze inmiddels teruggezet. 

huidige curl ziet er dan zo uit 

--location
--header "Authorization: Bearer token"
--header "Content-Type: multipart/form-data"
--form "attachment=@$$uploadfile"
--form "document={\"carrierCode\":\"FDXE\",\"contentType\":\"application/pdf\",\"meta\":{\"destinationCountryCode\":\"NL\",\"originCountryCode\":\"NL\",\"shipDocumentType\":\"COMMERCIAL_INVOICE\",\"shipmentDate\":\"2023-08-19T17:55:25\",\"trackingNumber\":\"794791292805\"},\"name\":\"invoice.pdf\",\"workflowName\":\"ETDPostshipment\"}"
--form "name=invoice.pdf"
-D $header

Krijg nog steeds attachment not present error.  Ik vraag me in deze vorm dus af of hij de "attachment=@$$uploadfile"  niet direct zo doorstuurt omdat het dus tussen aanhalingstekens staat binnen de quotefunctie.  Zet filemaker hier wel het bestand, of het pad naar het bestand toe, of wordt het als gewone string behandeld?

het valt me wel op dat de insert to URL scriptstap nu wel echt een aantal seconden in beslag neemt ( met het balkje dat er data wordt geupload), dus ik denk  dat er wel een bestand wordt meegestuurd. Bij de onderstaande varianten op de scriptstap is deze dataoverdracht namelijk een stuk korter. 

Het resultaat hierboven wordt gevormd met "--form " & Quote("attachment=@$$uploadfile") ; 

als ik de list opbouw met : "--form " & Quote("attachment=@" & $$uploadfile) ;

of met "--form " & Quote("attachment=@") & $$uploadfile ; 

dan is de resulterende curl in beide gevallen  --form "attachment=@"  dus leeg.  

Ik blijf nog even doorploeteren.  Ik heb ergens een suggestie gezien over het gebruik van een programma dat wireshark heet, hiermee kan je schijnbaar in depth zien wat  voor data er precies wordt verstuurd, misschien vind ik daar een aanwijzing over wat er mis gaat

 

Link to comment
  • 0

oke ik ben door deze post iets verder gekomen:

https://stackoverflow.com/questions/58965326/filemaker-18-curl-not-post-file-contents

inplaats van set variable -> container

heb ik gedaan: insert file ( bestand) 

dit geeft me nu ee nerror 100 en 400,

{    "customerTransactionId": "",    "errors": {        "code": "1021",        "message": "Uploaded file is not of correct type."    }}

 

in elk geval komt er nu een bestand aan :D 

Link to comment
  • 0
1 minuut geleden, Samsup zei:

   {"customerTransactionId": "",    "errors": {        "code": "1021",        "message": "Uploaded file is not of correct type."    }}

Ja die fout krijg ik ook, dus ik denk dat je het nu correct doet. Ik heb zojuist met mijn testbestand in de FMCommunity een vraag gesteld of anderen kunnen zien wat daar fout gaat: https://community.claris.com/en/s/question/0D53w00006DxotLCAR/trouble-uploading-documents-to-fedexapi-with-insertfromurl-uploaded-file-is-not-of-correct-type

Link to comment
  • 0

Ik kan bevestigen dat het inderdaad werkt. 

Ik had in geen miljoen jaar de oplossing kunnen verzinnen zoals Alex het heeft gedaan, maar het werkt!!!!

Ik heb je testbestand bekeken,  ik heb veel te leren over goede scripts bouwen zie ik wel weer . Ik zie dat je bijna alles in LET functies stopt.  Begrijp ik het goed dat het te vergelijken is met set variable scriptstappen?, maar dan voor meerdere variabelen in 1x? Ik vind het erg moeilijk te lezen/volgen die LET functies, dus ik doe het wel gewoon op mijn beun de haas manier voorlopig.  Kan nu in elk geval lekker verder klooien aan mn scriptje.. 

 

Ontzettend bedankt voor de energie die je hierin hebt gestoken! Geen idee hoe ik dit kan revancheren, maar mijn dank is groot! 

Link to comment
  • 0
Op 19-8-2023 om 19:48, Samsup zei:

Begrijp ik het goed dat het te vergelijken is met set variable scriptstappen?, maar dan voor meerdere variabelen in 1x?

Ja dat is exact wat er gebeurt. Ik vind het zelf gemakkelijker te gebruiken en te lezen, maar als je zo werkt moet je bij het ontwikkelen wel iets beter opletten. Het zoeken naar fouten is soms ook iets lastiger, maar de scripts worden er wél een stuk korter van... het heeft dus voor- en nadelen.

 

Op 19-8-2023 om 19:48, Samsup zei:

Geen idee hoe ik dit kan revancheren

Dat doe je al door de vraag te stellen en te bevestigen dat je het probleem hebt kunnen oplossen. Anderen komen ooit eenzelfde probleem tegen en hebben misschien ook iets aan deze oplossing. Mijn eigen motivatie ligt in diezelfde gedachte: ooit kom ik iets gelijkwaardigs tegen of heb misschien ergens anders hulp bij nodig.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...