File functionality

I have seen the File functionality being added recently. What are some of the api’s available to do the following.

Add directories
Delete directories
Add file
delete file

I am not able to find any documentation on this.

Thanks for bringing this to our attention! We had not updated the REST API documentation to include those new endpoints. The documentation is now there, and exists under the https://docs.losant.com/rest-api/files/ and https://docs.losant.com/rest-api/file/ pages.

Thanks. However, I do not see api’s for Add/delete directories.
Also, what should be the ‘content-type’ to POST a image .png file?
I do not see a fileID being returned not shown on the GUI. I see only the Name, lat updated and size being shown

Directories are just a “type” of file - see the type property of the file POST schema (https://docs.losant.com/rest-api/schemas/#file-post) - so you create them the same way you would create a file, just with the type property set to directory.

The standard content type for for a png image is image/png.

Currently, the id of a file (or directory) is not shown in the user interface, because if you are just interacting with the user interface, the id is not particularly useful or meaningful. Since you are also interacting through the API directly, I can see that value being useful - I’ll make a note that we should add it somewhere on the slide out properties pane.

Also, for regular files, after making the POST to Losant with the information about your file, you will get back (under the upload property in the response), a one-time use URL to upload the actual contents of the file to the Losant S3 File Store bucket. Your file will be marked as pending in the Losant interface until you actually use this URL to upload the contents of the file, at which point the file will be marked as completed.

I am not sure as to what to do with the one time URL I get. When I upload a image file within the GUI, I do not see “pending” - it gets completed and I can see the image. But not sure what I have to do when I do with API. My file uploaded is still in "wait’ state

You use the one-time URL to upload the actual contents of the file. It is a pre-signed S3 upload URL (https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html). When you upload a file through the Losant interface, it is doing this in your browser for you (making the POST to Losant, getting the signed URL, and then using that signed URL to upload the file to S3).

So why it is not doing the same way through API? why API users have to do this in two steps?

The Losant user interface is using the API directly, just as you are trying to do. It is just doing that second step for you, in your local browser. The reason it works as this two step process is to create the optimal experience for the Losant user interface, where it is much faster to upload the file contents from the browser directly to S3 instead of passing those file contents through the Losant API and server infrastructure.

Undersrtood. Can you please help me with the API interface setup to AWS if I have to test it out in postman uploading to the onetime URL I obtained.

I tried to PUT against the onetime URL with all the field values. I get this error

<?xml version="1.0" encoding="UTF-8"?> IllegalLocationConstraintException The unspecified location constraint is incompatible for the region specific endpoint this request was sent to. F64DA43A6A8B2E16 v3dumHV9pBi3kMBYgMaT7UKZN//MvxVJlRIc39pUEGKhJ+8WVQjk5FXrFIRO7GYLNAq1eGnNHZU=

When you make a files POST request to Losant, you will get back a JSON object with an upload field that has content similar to the following:

{
  "url": "https://s3.us-west-2.amazonaws.com/files.onlosant.com",
  "fields": {
    "Content-Type": "image/gif",
    "key": "5630dcbe1035c9d0011/file.js",
    "bucket": "files.onlosant.com",
    "X-Amz-Algorithm": "AWS4-HMAC-SHA256",
    "X-Amz-Credential": "AKIAJPGQGBQX4PYM6FXA/20180416/us-west-1/s3/aws4_request",
    "X-Amz-Date": "20180416T142402Z",
    "Policy": "a-large-policy-string",
    "X-Amz-Signature": "a-signature-string"
  }
}

In postman, you will want to make a POST to the value of the url property, and the post body should of type multipart/form-data. Every field in the fields object should be added to the post body except for the bucket field. In addition, add one more field named file, which should be the actual file.

I have in the header Content-Type as multipart/form-data

I get this error

<?xml version="1.0" encoding="UTF-8"?> MalformedPOSTRequest The body of your POST request is not well-formed multipart/form-data. A68DA0066BCB833D xpeu/HlZMz6APWDvbC1Qk3cSA35cxPRBRqYd9oc5IMsNiwUXfgwP6oaUVv2vg3vmD8RiYOEnx98=

I just made an attempt in Postman myself, to make sure there wasn’t anything I was missing, and my attempt succeeded:

It doesn’t look like I explicitly have to set the multipart/form-data header, Postman does it for you, so if you are doing that, perhaps remove it?

so for the file field value in postman, I cannot give the reference of the filepath in Losant as in the key. Is this correct?

the “file” field in postman should be the actual file - in postman (at least my version), you say that it is a form field of type file and then it lets you browse for the file on your computer.

In postman it is easy to give the filename. But in an HTTP request, how do I give the file attribute the value of the filename. Is there any other key I need to specify to go with file attribute.

Are you looking for how to do this in javascript in a browser? If so, you can use the FormData class and the File class. You get back an instance of the File class from any HTML input field of type file, and you can hand such an instance to an instance of FormData when building your post request. For example, it could work something like the following:

var fileInstance = /* get the file instance from your form here */;
var formData = new FormData();
formData.append('file', fileInstance);
/* append the other required upload form fields here */
var xhr = new XMLHttpRequest();
xhr.open('POST', theUrlToUploadTo, true);
xhr.send(formData);

Using formdata will not work for me as I will not be able to have an input type='file. I do not have a form to create in my gui interface.

I am trying to upload directly to the S3 bucket, that comes in the upload fields attribute(files.onlosant.com). What should be the AWS credentials settings should be.

I am trying like this … not sure as to what I should set for AWS config …

				AWS.config.region = 'us-west-2'; alert(AWS.config.region);
				AWS.config.accessKeyId = fields["X-Amz-Credential"];
				AWS.config.secretAccessKey = fields["X-Amz-Signature"];
				var bucket = new AWS.S3({params: {Bucket: 'files.onlosant.com'}});
                var blobData = dataURItoBlob(lnk.href);//alert("lnk.href=" + lnk.href);
                var fileName = fields["key"];
                var params = {Key: fileName, ContentType: fields["Content-Type"],Policy:fields["Policy"],'X-Amz-Algorithm':fields["X-Amz-Algorithm"],'X-Amz-Credential':fields["X-Amz-Credential"],'X-Amz-Date':fields["X-Amz-Date"],'X-Amz-Signature':fields["X-Amz-Signature"] ,Body: blobData};

alert("params = " + params[“X-Amz-Signature”]);
bucket.upload(params, function (err, data) {
console.log(err, data);
console.log(err ? ‘ERROR!’ : ‘UPLOADED.’);
});

dataURItoBlob is a function I am using to convert base64 data to a blob (like a file handle). My file is an image/png file.

Looks like my AWS config setting is not appropriate. Please let me know how to upload to S3 bucket

My dataURItoBlob function is as below …

function dataURItoBlob(dataURI) {alert("in blob=" + dataURI.split(',')[1]);
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/png'});
}

FormData is still what you want to be using - if you read the FormData Documentation, you will see that you can append a Blob to the form.

So something like the following should work:

var fileBlob = dataURItoBlob(lnk.href);
var formData = new FormData();
formData.append('file', fileBlob);
/* append the other required upload form fields here */
var xhr = new XMLHttpRequest();
xhr.open('POST', theUrlToUploadTo, true);
xhr.send(formData);
1 Like