IDOL View Document issue - salesforce

I am using IDOL API to convert a pdf file to html in Salesforce Apex class.
When I am using simple html, like:
<html>
<body>
<form action="https://api.idolondemand.com/1/api/sync/viewdocument/v1"
method="Post" enctype="multipart/form-data">
<input type="hidden" name="raw_html" value="true"/>
<input type="hidden" name="apikey"
value="{apikey removed}"/>
<input type='FILE' name='file'/><br/>
<input type='submit' name='upload_btn' value='Submit'/>
</form>
</body>
</html>
then this is working. But when I am using APEX code httprequest, then this is making a bad request.
My APEX code is:
public HTTPResponse uploadFile(Attachment file){
//String boundary = '---------------------\n';
String header = '\n';
header += 'Content-Disposition: form-data; name="file"; filename="'
+ file.Name +'"\nContent-Type: application/pdf\n\n';
String footer = '\n';
String querybody = '\n Content-Disposition: form-data;
name="raw_html"\n\n'+true+'\n';
querybody = querybody + '\n Content-Disposition: form-data;
name="apikey"\n\n {apikey removed} \n\n';
//base64 encoded body
String bodyEncoded = EncodingUtil.base64Encode(file.body);
//last encoded body bytes
String last4Bytes =
bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
//if the last 4 bytes encoded base64 ends with the padding character (=
or ==) then re-encode those bytes with the footer
//to ensure the padding is added only at the end of the body
if(last4Bytes.endsWith('='))
{
Blob decoded4Bytes = EncodingUtil.base64Decode(last4Bytes);
HttpRequest tmp = new HttpRequest();
tmp.setBodyAsBlob(decoded4Bytes);
String last4BytesFooter = tmp.getBody()+footer;
bodyEncoded = querybody + header +
bodyEncoded.substring(0,bodyEncoded.length()-4) +
EncodingUtil.base64Encode(Blob.valueOf(last4BytesFooter)) +
footer;
}
else
{
bodyEncoded = querybody + header + bodyEncoded + footer;
}
bodyEncoded = querybody;// + header + bodyEncoded + footer;
System.debug('>>>>>>>>>>>>>>>>>>>>>>' + bodyEncoded);
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type','multipart/mixed');
req.setMethod('POST');
req.setEndpoint('https://api.idolondemand.com/1/api/sync/viewdocument/v1'
);
req.setBody(bodyEncoded);
req.setTimeout(120000);
req.setHeader('Content-Length', String.valueof(req.getBody().length()));
Http http = new Http();
Httpresponse res = http.send(req);
return res;
}
My Visual force page containing only:
<apex:page controller="IDOLService">
<apex:form >
<apex:pageBlock title="File Input">
<apex:pageBlockSection >
<apex:pageBlockSectionItem >
<apex:inputFile value="{!file.body}" filename="{!file.Name}"/>
<apex:commandButton action="{!showPreview}" value="Show Preview"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
<apex:outputpanel id="docpanel">
{!result}
</apex:outputpanel>
</apex:form>
</apex:page>
This is giving me error of 7005, bad request.

We tried reproducing using the supplied code but it’s hard to reproduce properly without the remainder of the IDOLService controller code that has seemingly been omitted. We haven’t tried http posting multi-part forms from apex before (and a glance at some other questions suggests it’s not entirely simple) so it will take a bit of time to put together a working example.
Please can you send more information to idolondemand(at)hp.com so that the team can do a more in-depth review?
Regards,
hughesthe1st
(I work for HP)

Related

Codename One - MultipartRequest to send screenshot of the app, error code 400

I can send a file and some extra data to my REST server by a POST request mapped to "/".
This is an example of working HTML code, using this form the server stores a file and some metadata (appID, description):
<form method="POST" enctype="multipart/form-data" action="/">
<table>
<tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
</table>
<input type="hidden" name="appID" value="uploadForm" />
<input type="hidden" name="description" value="example of description" />
</form>
I need to send a screenshot of the app using this POST request.
I wrote a method that seems to save correctly the file "screenshot.png" (I found that file in the .cn1 folder used by the Simulator), but the POST request fails with an HTTP Error Code 400 (shown in a Dialog). What's wrong in the following method? Please assume that the previous HTML code works without errors, I expect to do the same with Codename One.
The logs report the following information, the URL of the server is correct:
[EDT] 0:0:17,736 - Storage URL for POST multipart request:
http://localhost:8090/
[EDT] 0:0:17,738 - Screenshot file to send:
file://home/screenshot.png
public static void sendScreenshotToCloud(Form form, String info) {
if (form == null) {
form = getCurrentForm();
}
Image screenshot = Image.createImage(form.getWidth(), form.getHeight());
form.revalidate();
form.setVisible(true);
form.paintComponent(screenshot.getGraphics(), true);
ImageIO imgIO = ImageIO.getImageIO();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
imgIO.save(screenshot, out, ImageIO.FORMAT_PNG, 1);
} catch (IOException err) {
Log.e(err);
}
byte[] ba = out.toByteArray();
try (OutputStream os = Storage.getInstance().createOutputStream("screenshot.png")) {
os.write(ba);
} catch (IOException err) {
Log.e(err);
Log.sendLog();
}
MultipartRequest request = new MultipartRequest();
request.addResponseListener((e) -> {
// process the response
if (e.getResponseCode() == 200) {
Log.p("Screenshot uploaded to the cloud successfully");
ToastBar.Status status = ToastBar.getInstance().createStatus();
status.setMessage("Screenshot sent...");
status.show();
UITimer.timer(2000, false, () -> status.clear());
} else {
Log.p("ERROR in sending the screenshot to the cloud");
ToastBar.Status status = ToastBar.getInstance().createStatus();
status.setMessage("ERROR: cannot send screenshot...");
status.show();
UITimer.timer(2000, false, () -> status.clear());
}
});
String url = RestRequest.getInstance().getConnectionRequestStorageURL("");
String filePath = getAppHomePath()+"screenshot.png";
Log.p("Storage URL for POST multipart request: \n" + url);
Log.p("Screenshot file to send: \n" + filePath);
request.setUrl(url);
try {
request.addData("file", filePath, "image/png");
} catch (IOException ex) {
Log.e(ex);
Log.sendLog();
}
request.addArgument("appID", RegisterApp.getAppID());
// request.addArgument("description", info + Miscellaneous.getAllLogs());
NetworkManager.getInstance().addToQueue(request);
ToastBar.Status status = ToastBar.getInstance().createStatus();
status.setMessage("Uploading...");
status.show();
UITimer.timer(2000, false, () -> status.clear());
}

Download report from jsreport and angularjs

I'd like to know how could I make a report downloadable from my AngularJS Application?
The report is a .xlsx I can post the data, but the response is:
What I'd like is a downloadable file, or to open the .xlsx on Excel Online in other tab as in the preview.
How could I do that?
I usually recommend to create a hidden form and do plain http submit to jsreport /api/report. This is the most stable way and works across all browsers.
<form method='POST' target='_blank' action='/api/report' id='jsrForm'>
<input hidden='true' name='template[shortid]' value="41ucBgXKe"/>
<input hidden='true' name='data[foo]' value="Hello world"/>
<input hidden='true' name='options[Content-Disposition]' value="attachment; filename=myreport.pdf"/>
</form>
<script>
document.getElementById("jsrForm").submit();
</script>
Do you have control over the response? If so, add the content-disposition header and MediaType header to the response:
For System.Net.Http.HttpResponseMessage
var response = new HttpResponseMessage{Content = ...........}
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = "mydoc.xlsx"
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
For System.Net.WebClient
var client = new WebClient();
client.Headers.Add("Content-disposition", "attachment");
client.Headers.Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

Curious case of webapi put request (FromBody model ) not getting populated with angular $resource

I have a Webapi controller as below .
Pretty crude though .
public async Task<HttpResponseMessage> Put(string id, [FromBody]Students studentToupdate)
{
if (!ModelState.IsValid)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, "Model state Not valid");
}
if (studentToupdate == null)
return new HttpResponseMessage(HttpStatusCode.BadRequest);
Students student = await Context.Set<Students>().FindAsync(new Guid(id));
student.FirstName = studentToupdate.FirstName;
student.LastName = studentToupdate.LastName;
student.Address = studentToupdate.Address;
student.DOB = studentToupdate.DOB;
student.Phone = studentToupdate.Phone;
Context.Entry(student).State = EntityState.Modified;
try
{
int result = await Context.SaveChangesAsync();
return result > 0 ? Request.CreateResponse<Students>(HttpStatusCode.OK, student) : Request.CreateResponse(HttpStatusCode.InternalServerError);
}
catch (Exception ex)
{
return Request.CreateResponse<Exception>(ex);
}
}
My angular controlller is something like this .Its in coffeescript .
SiteAngular.Student.controller 'Edit',['$scope','$state','$stateParams','Factory',($scope,$state,$stateParams,factory)->
id=$stateParams.id
student = factory.get id:id
$scope.student=student
$scope.Update = (id,student)->
factory.update
id:id
studentToupdate:student
]
And last not the least my html is likely to be a list and its button has a update method as :
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" value="Save" class="btn btn-default" ng-click="Update(student.StudentGuid,student)"/>
</div>
</div>
above the div I have ng-repeat to looped into table for various properties for student . and in the update method I want to send the Guid and the student object to mentioned webapi controller
The problem is this in webapi controller string id received the guid perfectly . However all the properties of studentToUpdate is null . I checked the header its perfectly to be like
Accept application/json, text/plain, */*
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Content-Length 250
Content-Type application/json;charset=utf-8
Cookie __RequestVerificationToken=SBC0HZDwZOEyOfG0dMN0Da-MqFYQoVoiaG3_LIpnXc5a4tSsu1wP4U8Qy3cgrw7w_rMmDu5577pVrZ0Kmzo9YCZcLvFY93f37Heat160h6k1
Host localhost:3090
Referer http://localhost:3090/
User-Agent Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Can somebody tell me why the id gets populated and not the FromBody student object . The properties of student object in webapi put method is all null??
using webapi v5.1.0.0. Any clues ?
I have the answer . The update put should have been likely to be
$scope.Update = (id,student)->
factory.update
id:id
student
]
The parameter key studentToupdateisn't required it automatically gets resolved while getting passed as jquery json object .

JSON HTTP object retieval in Salesforce

Apex Class -->
public class Json_Callout{
public static string response;
// Pass in the endpoint to be used using the string url
public static string getContent() {
system.debug('++++++++++++++++++++++++++++In side the Method Get Content');
String url = 'http://180.211.69.30:8080/JhImpl/WS/implService/upload';
// Instantiate a new http object
Http h = new Http();
try {
system.debug('++++++++++++++++++++++++++++In side the Try Block');
// Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
HttpRequest req = new HttpRequest();
req.setHeader('abc', 'abc');
req.setEndpoint(url);
req.setMethod('GET');
// Send the request, and return a response
HttpResponse res = h.send(req);
system.debug('Result==========================================='+res);
system.debug('REsult for Variable=============================='+res.getBody());
response = res.getStatus();
String contact = response;
return res.getBody();
}
catch(System.CalloutException ex) {
system.debug('catch'+ex);
}
}
}
Apex Page -->
<apex:page Controller="Json_Callout" tabStyle="Account">
It will be a nice to get output from the controller
<apex:pageBlock title="Hello {!$User.FirstName}!"/>
<apex:form >
<apex:commandButton value="Go!" action="{!getContent}"/>
</apex:form>
<!--<apex:variable var="c" value="{!contact}" />-->
<!--<apex:pageMessages>
</apex:pageMessages>-->
</apex:page>
How do i retrieve the Json Object , in order to Parse it.
I have system.debug the response.getBody() which is giving me the status code = 200 , that means i am able to hit the service , but how do i get the Json Object and the response so as to Parse it and also reflecting back it into the Apex Page .
I am getting the error that The name can only contain underscores and alphanumeric characters. It must begin with a letter and be unique, and must not include spaces, end with an underscore, or contain two consecutive underscores.
Thanks.

Uploading a file to google drive from appengine (python)

I'm trying to upload a file to google drive from google app engine.
I have tried 2 different ways but I lose information in both.
The first one is the next one:
-The html form:
<html><body><form id='myForm' method='post' action='/guardar'
enctype='multipart/form-data' >
<input type="file" id="doc" name="doc" >
<input type="submit" value="Enviar"></form>
</body></html>
-The python code:
class guardar(webapp.RequestHandler):
#decorator.oauth_required
def post(self):
http = decorator.http()
service = build('drive', 'v2', http=http)
thefile = self.request.get('doc')
media_body = MediaInMemoryUpload(thefile, mimetype='text/plain', resumable=True)
response = service.files().insert(body={'title': 'prueba_si','mimeType': 'text/plain'},media_body=media_body).execute()
This way I lose the mimetype of the uploaded file and the title too; and I need both.
I have tried this other way but it always says that such file does not exist:
-The html file:
<html><body><form id='myForm' method='post' action='/guardar' >
<input type="file" id="doc" name="doc" >
<input type="submit" value="Enviar"></form>
</body></html>
-The python code:
class guardar(webapp.RequestHandler):
#decorator.oauth_required
def post(self):
http = decorator.http()
service = build('drive', 'v2', http=http)
thefile = self.request.get('doc')
mime_type=mimetypes.guess_type(thefile,strict=True)
media_body = MediaFileUpload(filename, mimetype=mime_type, resumable=True)
response = service.files().insert(body={'title': 'prueba_si','mimeType': mime_type},media_body=media_body).execute()
Thanks a lot for the help!
You don't need to pass the mime type in the media upload and also in the metadata. I would leave it just in the media upload.
You should not lose the title information, but I cannot reproduce your error.

Resources