Pentaho - upload file using API - pentaho

I need to upload a file using an API.
I tried REST CLIENT and didn't find any options.
Tried with HTTP POST and that responded with 415.
Please suggest how to accomplish this

Error 415 is “Unsupported media type”.
You may need to change the media type of the request or check whether that type of file us accepted by the remote server.
https://en.m.wikipedia.org/wiki/List_of_HTTP_status_codes

This solution uses only standard classes of jre 7. Add a step Modified Java Script Value in your transformation. You will have to add two columns in the flow: URL_FORM_POST_MULTIPART_COLUMN and FILE_URL_COLUMN, you can add as many files as you want, you will just have to call outputStreamToRequestBody.write more times.
try
{
//in this step you will need to add two columns from the previous flow -> URL_FORM_POST_MULTIPART_COLUMN, FILE_URL_COLUMN
var serverUrl = new java.net.URL(URL_FORM_POST_MULTIPART_COLUMN);
var boundaryString = "999aaa000zzz09za";
var openBoundary = java.lang.String.format("\n\n--%s\nContent-Disposition: form-data\nContent-Type: text/xml\n\n" , boundaryString);
var closeBoundary = java.lang.String.format("\n\n--%s--\n", boundaryString);
// var netIPSocketAddress = java.net.InetSocketAddress("127.0.0.1", 8888);
// var proxy = java.net.Proxy(java.net.Proxy.Type.HTTP , netIPSocketAddress);
// var urlConnection = serverUrl.openConnection(proxy);
var urlConnection = serverUrl.openConnection();
urlConnection.setDoOutput(true); // Indicate that we want to write to the HTTP request body
urlConnection.setRequestMethod("POST");
//urlConnection.addRequestProperty("Authorization", "Basic " + Authorization);
urlConnection.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundaryString);
var outputStreamToRequestBody = urlConnection.getOutputStream();
outputStreamToRequestBody.write(openBoundary.getBytes(java.nio.charset.StandardCharsets.UTF_8));
outputStreamToRequestBody.write(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(FILE_URL_COLUMN)));
outputStreamToRequestBody.write(closeBoundary.getBytes(java.nio.charset.StandardCharsets.UTF_8));
outputStreamToRequestBody.flush();
var httpResponseReader = new java.io.BufferedReader(new java.io.InputStreamReader(urlConnection.getInputStream()));
var lineRead = "";
var finalText = "";
while((lineRead = httpResponseReader.readLine()) != null) {
finalText += lineRead;
}
var status = urlConnection.getResponseCode();
var result = finalText;
var time = new Date();
}
catch(e)
{
Alert(e);
}

I solved this by using the solution from http://www.dietz-solutions.com/2017/06/pentaho-data-integration-multi-part.html
Thanks Ben.
He's written a Java class for Multi-part Form submission. I extendd by adding a header for Authorization...

Related

How to get request body in angular from ActivatedRoute

As i can get the query params by using ActivatedRoute which is get request. but how can i get request body by using ActivatedRoute from post request. If ActivatedRoute is not right option to get then how should i get request body
This is my jsp code:-
var res = "url which i am creating";
var url =res[0];
var mapForm = document.createElement("form");
mapForm.target = "Test";
mapForm.method = "post";
mapForm.action = url;
//Splitting parameters from url to add into body
var res1 =res[1].split("=");
var name = res1[0];
var value = res1[1];
mapInput3 = document.createElement("input");
mapInput3.type = "hidden";
mapInput3.name =name;
mapInput3.value = value;
mapForm.appendChild(mapInput3);
document.body.appendChild(mapForm);
map = window.open("", "Test", "menubar,
toolbar, location, directories, status, scrollbars,
resizable, dependent, width=1200, height=600,
left=0,top=0");
if (map) {
mapForm.submit();
}
this is my angular code:-
this.activeRoute.queryParams.subscribe(params => {
this.authKey = params['auth_key'];
});
Now if I sent parameter through get method from jsp, I am able to get it from above angular code.
but if i sent params through post method then i get message as " Cannot post"
If I got you right you want to get the body of the query.
You can use snapshot.get and when declare a it with a value something like this ->
const t = this.route.snapshot.mapedQuery.get()
The value of- t is your query body.
Answered from my phone so I can’t format the code

AWS S3 CopyObjectAsync fails with key does not exist, but get/put succeeds

I fought with this for several hours and never found the solution. Here's the scenario:
var copyObjectRequest = new CopyObjectRequest
{
SourceBucket = s3Event.S3.Bucket.Name,
SourceKey = s3Event.S3.Object.Key,
DestinationBucket = OutputBucketName,
DestinationKey = s3Event.S3.Object.Key,
};
var deleteRequest = new DeleteObjectRequest
{
BucketName = copyObjectRequest.SourceBucket,
Key = copyObjectRequest.SourceKey,
};
await S3Client.CopyObjectAsync(copyObjectRequest);
await S3Client.DeleteObjectAsync(deleteRequest);
S3Client.CopyObjectAsync throws the error: "The specified key does not exist." (S3Client.DeleteObjectAsync is never reached.)
However, the following code works (for the same values):
var request = new GetObjectRequest
{
BucketName = copyObjectRequest.SourceBucket,
Key = copyObjectRequest.SourceKey,
};
var response = await S3Client.GetObjectAsync(request);
var tempPath = $"{Guid.NewGuid():D}";
await response.WriteResponseStreamToFileAsync(tempPath, false, CancellationToken.None);
var putRequest = new PutObjectRequest
{
BucketName = copyObjectRequest.DestinationBucket,
Key = copyObjectRequest.DestinationKey,
FilePath = tempPath,
};
var putResponse = await S3Client.PutObjectAsync(putRequest);
if (putResponse.HttpStatusCode == HttpStatusCode.OK)
{
var deleteRequest = new DeleteObjectRequest
{
BucketName = copyObjectRequest.SourceBucket,
Key = copyObjectRequest.SourceKey,
};
await S3Client.DeleteObjectAsync(deleteRequest);
}
For brevity I removed almost all error checking, logging, etc. but if requested I'm happy to share the full function.
Note that this is running in a C# Lambda Function, using Core 2.0.
I've ruled out security as the second set of calls requires the same permissions (I believe) as the CopyObject call does (please do correct me if I'm wrong).
There's no doubt the object is at the bucket and key specified as the second set uses the exact same structure.
The key doesn't exist in the destination bucket.
Both the source and destination buckets have the same permissions.
There are no special characters in the key (sample keys that I've tested are "/US/ID/Teton/EC2ClientDemo.zip" and "testkey").
The files I'm testing with are tiny (that sample file is 30Kb).
I've tried it with and without a CannedACL value in CopyObjectRequest (I don't think it should require one for my purposes, all the files it's moving around are private).
I've validated that all buckets are in the same region (USWest2).
I can't figure out why CopyObjectAsync fails. I've tried digging down through the disassembled code for CopyObjectAsync, but it's called so indirectly I didn't get very far. At this point my best guess is that it's a bug in CopyObjectAsync.
Any suggestions would be appreciated,
Thanks for reading!
Additional: I want to make it clear that this works from the regular AWSSDK library (either CopyObjectAsync or CopyObject), it only fails in the Core 2.0 async call CopyObjectAsync in the Lambda environment.
OK, so I figured it out and it is definitely a bug in the core 2.0 CopyObjectAsync(). Here's the scenario:
We are using keys that have slashes at the beginning, an example would be '/US/ID/Teton/EC2ClientDemo.zip'. When I turned on S3 logging (thank you #Michael-sqlbot) what I saw was this:
[13/Jul/2018:17:44:18 +0000] 34.221.84.59 arn:aws:sts::434371411556:assumed-role/LambdaFunctionCreation/TestFunction 489A5570C2E840AC REST.COPY.OBJECT_GET US/ID/Teton/EC2ClientDemo.zip - 404 NoSuchKey
As you can see the CopyObjectAsync() function stripped off the first slash before making the call. Get, Put, and Delete handle these particular keys just fine (and I tested this in the non-Core library and both the synchronous and asynchronous versions of CopyObjectAsync() handle the keys just fine as well).
What I had to do to fix it was the following:
var copyObjectRequest = new CopyObjectRequest
{
SourceBucket = s3Event.S3.Bucket.Name,
SourceKey = "/" + s3Event.S3.Object.Key,
DestinationBucket = OutputBucketName,
DestinationKey = "/" + s3Event.S3.Object.Key,
CannedACL = S3CannedACL.BucketOwnerFullControl,
};
Note the added slashes on the SourceKey and DestinationKey? Without those the keys are mangled.
Here is the complete final code:
var copyObjectRequest = new CopyObjectRequest
{
SourceBucket = s3Event.S3.Bucket.Name,
SourceKey = s3Event.S3.Object.Key,
DestinationBucket = OutputBucketName,
DestinationKey = s3Event.S3.Object.Key,
CannedACL = S3CannedACL.BucketOwnerFullControl,
};
try
{
await s3Client.CopyObjectAsync(copyObjectRequest);
}
catch (AmazonS3Exception ase) when (ase.Message.Contains("key does not exist"))
{
try
{
// If this failed due to Key not found, then fix up the request for the CopyObjectAsync bug in the Core 2.0 library and try again.
var patchedCopyObjectRequest = new CopyObjectRequest()
{
SourceBucket = copyObjectRequest.SourceBucket,
SourceKey = "/" + copyObjectRequest.SourceKey,
DestinationBucket = copyObjectRequest.DestinationBucket,
DestinationKey = "/" + copyObjectRequest.DestinationKey,
CannedACL = copyObjectRequest.CannedACL,
};
await s3Client.CopyObjectAsync(patchedCopyObjectRequest);
}
catch (AmazonS3Exception)
{
// Rethrow the initial exception, since we don't want a confusing message to contain the modified keys.
throw ase;
}
}

Zoho Creator API Integration Basic Authorization postUrl()

Here is my code and I am getting Internal Error for postural() call. By the way, one more thing I want to know how we can use verify_peer to 0(zero) for not using SSL things. What is wrong with my code?
void SendSMS(SMS SMSObject)
{
//CONFIGURATION
URL = "https://example.com/send_ack.php";
wbLogin = "wbLogin";
wbPwd = "wbPwd";
wbAccount = "wbAccount";
label = "label";
applicationName = "ADR SMS v1.0";
//BASE64 ENCODING
Base64Encoded = zoho.encryption.base64Encode("httpLogin:httpPwd");
AuthorizationBasic = "Authorization: Basic " + Base64Encoded;
//HEADER
HeaderMap = Map();
HeaderMap.put("content-type", "application/x-www-form-urlencoded");
HeaderMap.put("Authorization", AuthorizationBasic);
//REQUEST
RequestMap = Map();
RequestMap.put("compte", wbAccount);
RequestMap.put("op", 1);
RequestMap.put("type", 0);
RequestMap.put("dt", zoho.currentdate.getDay());
RequestMap.put("hr", zoho.currenttime.getHour());
RequestMap.put("mn", zoho.currenttime.getMinutes());
RequestMap.put("label", label);
RequestMap.put("dest_num", "phone_number");
RequestMap.put("msg", "ZC Testing");
RequestMap.put("ref", "ZC");
//CALL POSTURL
Result = postUrl(URL, RequestMap, HeaderMap, false);
//DEBUG
info Result;
}
Use Zoho Creator API for this purpose.

NetSuite API - How to send tracking number back to Invoice or Sales Order?

I'm integrating a shipping solution with NetSuite via the SOAP API. I can retrieve the shipAddress via the searchRecord call. Now I need to send the tracking number, service used, and cost back into NetSuite. Hoping someone can point me in the right direction as searching hasn't turned up any answers for me. An example XML would be great.
Im pretty much pasting what I was had an external developer attempt to implement as the response but I don't understand how to setup the envelope to receive it within NS on a record...I think this is what is handling the update post to Field:
'
var a = new Array();
a['Content-Type'] = 'text/xml; charset=utf-8';
a['POST'] = '/FedexNSService/Service1.asmx HTTP/1.1';
a['Content-Length'] = data.length;
a['SOAPAction'] = 'https://wsbeta.fedex.com:443/web-services/ship/ReturnFedexLable';
nlapiLogExecution('DEBUG', 'Results', 'data : ' + data);
var response = nlapiRequestURL('http://sonatauat.adaaitsolutions.com/FedexNSService/Service1.asmx?op=ReturnFedexLable', data, a, null,null);
nlapiLogExecution('DEBUG', 'response', response);
var responseXML = nlapiStringToXML(response.getBody());
nlapiLogExecution('DEBUG', 'responseXML', responseXML);
var responseCode = response.getCode();
nlapiLogExecution('DEBUG', 'responseCode', responseCode);
var body = response.getBody();
nlapiLogExecution('DEBUG', 'body', body);
nlapiLogExecution('DEBUG', 'responseXML '+responseXML, 'responseCode : ' + responseCode);
nlapiLogExecution('DEBUG', 'body ', 'body : ' +body);
var imageurl ='';
if(responseXML != null)
{
var rawfeeds = nlapiSelectNodes(responseXML, "//Tracking");
var FileInternalId = nlapiSelectValue(rawfeeds[0], "FileInternalId");
var TrackingIds = nlapiSelectValue(rawfeeds[1], "TrackingIds");
nlapiLogExecution('DEBUG', 'FileInternalId '+FileInternalId, 'TrackingIds : '+TrackingIds );
if(FileInternalId)
{
var image=nlapiLoadFile(5985);
imageurl=image.getURL();
imageurl = ("https://system.netsuite.com"+imageurl);
nlapiLogExecution('DEBUG','image',imageurl);
}
}
return imageurl;
'
In order to update a sales order with the information via SOAP you need to create a sales order object, set the values and call either an update, or an upsert method:
[JAVA]
SalesOrder so = new SalesOrder();
so.setExternalId("externalID"); //This should correspond to the previous external ID for updates.
...set_other_fields_as_required...
WriteResponse wr = ns.getPort().update(so); //ns = _port if you're using the samples
[C#]
var so = new SalesOrder();
so.externalId = "externalID";
...set_other_fields_as_required...
var wr = Service.upsert(so);
PHP should be similar, but I haven't used the PHP toolkit so I can't say for certain.
This should help get you started.

Eventbrite API date range parameter for organizer_list_events

I need a way to search via the eventbrite api past events, by organizer, that are private, but I also need to be able to limit the date range. I have not found a viable solution for this search. I assume the organizer_list_events api would be the preferred method, but the request paramaters don't seem to allow for the date range, and I am getting FAR too many returns.
I'm having some similar issues I posted a question to get a response about parsing the timezone, here's the code I'm using to get the dates though and exclude any events before today (unfortunately like you said I'm still getting everything sent to me and paring things out client side)
Note this is an AngularJS control but the code is just using the EventBrite javascript API.
function EventCtrl($http, $scope)
{
$scope.events=[];
$scope.noEventsDisplay = "Loading events...";
Eventbrite({'app_key': "EVC36F6EQZZ4M5DL6S"}, function(eb){
// define a few parameters to pass to the API
// Options are listed here: http://developer.eventbrite.com/doc/organizers/organizer_list_events/
//3877641809
var options = {
'id' : "3588304527",
};
// provide a callback to display the response data:
eb.organizer_list_events( options, function( response ){
validEvents = [];
var now = new Date().getTime();
for(var i = 0; i<response.events.length; i++)
{
var sd = response.events[i].event.start_date;
var ed = response.events[i].event.end_date;
var parsedSD = sd.split(/[:-\s]/);
var parsedED = ed.split(/[:-\s]/);
var startDate = new Date(parsedSD[0], parsedSD[1]-1, parsedSD[2], parsedSD[3], parsedSD[4], parsedSD[5]);
var endDate = new Date(parsedED[0], parsedED[1]-1, parsedED[2], parsedED[3], parsedED[4], parsedED[5]);
if(endDate.getTime()<now)
continue;
response.events[i].event.formattedDate = date.toDateString();
validEvents.push(response.events[i])
}
if(validEvents.length == 0)
{
$scope.$apply(function(scope){scope.noEventsDisplay = "No upcoming events to display, please check back soon.";});
}
else
{
$scope.$apply(function(scope){scope.noEventsDisplay = "";});
}
$scope.$apply(function(scope){scope.events = validEvents;});
//$('.event_list').html(eb.utils.eventList( response, eb.utils.eventListRow ));
});
});
}