Support Topics Documentation Slack YouTube Blog

File upload from Appgyver

Haha touche @mark-piller. And agree.
The native app (ability to run local storage), and charting (google charts plugin) I’d say are the main differentiators. I essentially built an mvp on backendless’ front/back end and had to switch to appgyver for a front end when I discovered the charting options. I’d be happy to beta any features you guys are working to help refine/grow your product.

Do we need to complete the missions to use the Backendless API for the free version?

You can you use backendless api at any point as long as the app is not suspended. Missions can be used to unlock the Springboard plan

thanks !

In the documentation for the API it shows the format using curl, but is there a way to reflect how that format translates to a web call? Like where does the --form piece go? can it go in the URL as a parameter?

curl -H Content-Type:“multipart/form-data” \
–form upload=@test.txt \
-X POST \
-v http://api.backendless.com/XXXX-XXXXX-XXXX/ZZZZ-ZZZZ-ZZZZZ/files/txtfiles/test.txt

(I may not be making any sense at all here, just trying to understand how my phone would make a rest call without having curl…)

Ok a different approach - how do I need to enter these details to get this to work on Postman?


?
And then…

?

If I can get this to work then I’ll see if I can reverse engineer it over to my app

Hi, @Joel_Maclean

You do not need to enter any data in the key field which is in the body. Just select the key as a file and in the value there will be an opportunity to select the file from your machine.


Regards,
Marina

Thanks Marina, but I still get a boundary error message, I must be missing a piece somewhere?

@mark-piller . Hi mark, I wonder if you can help. I am still getting response 400 from Backendless when upload from Appgiver

Here is the code in the response. Does it explain anything that is meaningful to you? Many thanks

Object {type: “default”, status: 400, ok: false, headers: Object, url: “https://api.backendless.com/A7CE5EE9-FE79-4C3E-A4B0-XXXXXXXX/49416C8D-1E7F-4957-B5E4-XXXXXXXXX/files/testphotos/Screenshot_20210509_200134.jpg”…}

  1. type: “default”

  2. status: 400

  3. ok: false

  4. :arrow_forward:headers: Object

  5. :arrow_forward:map: Object

1. strict-transport-security: "max-age=86400"

2. access-control-allow-methods: "POST, GET, OPTIONS, PUT, DELETE, PATCH"

3. access-control-allow-origin: "*"

4. content-length: "112"

5. content-type: "application/json"

6. date: "Tue, 11 May 2021 17:17:49 GMT"

7. server: "nginx"
  1. url: “https://api.backendless.com/A7CE5EE9-FE79-4C3E-XXXXXXXXX/49416C8D-1E7F-4957-B5E4-XXXXXXXXXX/files/testphotos/Screenshot_20210509_200134.jpg

  2. bodyUsed: false

  3. :arrow_forward:_bodyInit: Object

  4. :arrow_forward:_data: Object

1. size: 112

2. offset: 0

3. blobId: "b2f2b02e-e31c-4212-80df-6e207f28b49e"

4. __collector: null
  1. :arrow_forward:_bodyBlob: Object

  2. :arrow_forward:_data: Object

1. size: 112

2. offset: 0

3. blobId: "b2f2b02e-e31c-4212-80df-6e207f28b49e"

4. __collector: null

@mark-piller - thanks this is solved

I needed to use eu-api.backendless as this is my cluster

It would be helpful if this was in the documentation for eg file uploads etc

Many thanks

Figured it out, you SHOULD NOT be specifying the content type when using Postman.
So I know the url is correct and it can find the file locally, now I just need to figure out how to attach the file into the body of the REST call in appgyver…

@Joel_Maclean - you are right, postman automatically adds the content type (but when I added it anyway, its still works) , it just sends twice

Anyway - I have finally done it!

  1. if you are in europe (using european backendless ) the your URL MUST start:
    eu-api.backendless.com

  2. Start with just a Pick Image flow function (even if you want Take photo, which will work also)

  3. Make a java script block Flow Function

  4. Join the output from the the Pick Image to the Javascript Flow Function

  5. Set the inputs in the JavaScript FF like this:

you can see where you put api key and app ID . Also the most important one is the second one down which you set to output of another node and choose the image object (which contains the 6 image properties) . The filename , you can put what you want to test eg “testpic.jpg” , but in the end I put it to the image.name property

then use this Javascript Code
(Im sorry it only lets me copy image not, the text!!)

the outputs setup wont stop it working if wrong, but you prob want to know the response from the Backendless, so join it to Alert or Debug

Great job @sim_sim ! I too figured it out but using a different method so that I could use the file storage option as opposed to saving images in the database.

  1. In Appgyver I used a webview control to call the backendless file uploader control
  2. In the webview URL I pass a parameter on the end that indicates the filename for backendless to use
  3. In backendless I extract the filename parameter from the url and save the file in the file storage with that filename (as opposed to saving the file as a record in a table)
  4. Because I know the filename and destination path, in Appgyver I save the full url to the saved file in my table
  5. voila its available to display as an image in Appgyver

OK thats great! I might try that

Here is the full way I did it, I posted it up at Appgyver. Perhaps you could post a full solution of yours there too, the at least people have a chance of doing it themselves

1 Like

// A generalized version for multiple files of different types and different outputs, it takes “Pick Files” as input.

const { path, count, app_id, app_key, overwrite, fileObjects, user_token, user_id, unique_suffix } = inputs;

const files = new Array(count);
for (var j = 0; j < files.length; j++) files[j] = fileObjects[j];

const responses = new Array(files.length);
for (var idx = 0; idx < files.length; idx++) responses[idx] = await uploadFile(idx);

async function uploadFile(idx) {

 let n = files[idx].name.lastIndexOf("\.");
 if (n < 0) n = files[idx].name.length;

 let url = `https://api.backendless.com/${app_id}/${app_key}/files/${path}/${encodeURIComponent(files[idx].name.substring(0,n)+unique_suffix+files[idx].name.substring(n))}?overwrite=${overwrite}`;

 let formData = new FormData();
 let file = {
                uri: files[idx].path,
                name: files[idx].name,
                size: files[idx].size,
                type: files[idx].mimeType,
                createdAt: files[idx].createdAt,
                modifiedAt: files[idx].modifiedAt,
                uploadUrl: url.slice()
            };

 formData.append('fileToUpload', file);
 return ( await fetch(url, {
                               method: 'POST',
                               headers: {
                                         'Content-Type': 'multipart/form-data',
                                         'user-token': user_token,
                                         'id' : user_id,
                               },
                               body: formData,
                           }
                     )
        );

}

const successes = responses.filter(uploadResult => uploadResult.status == 200);
const errors = responses.filter(uploadResult => uploadResult.status >= 400);

let output_idx = 1;
if (successes.length > 0 && successes.length == files.length) output_idx = 0;
if (errors.length == responses.length) output_idx = 2;

{
return [ output_idx, { result : JSON.stringify(responses) } ];
}