suitescript: POST an image form the cabinet multipart/form-data - multipartform-data

I am trying to post an image form the cabinet to an API
the API is rejected call with Content-Type": "multipart/form-data:
{
httpCode: "405",
httpMessage: "Method Not Allowed",
message: "PUT, POST require an input body.",
errorClass: "Exception"
}
the API is rejected call without Content-Type": "multipart/form-data:
{
httpCode: "400",
httpMessage: "Bad Request",
message: "JSON Input was invalid. Error Message: Syntax error",
errorClass: "InvalidArgumentException"
}
the current code is:
function ItemImageCreation(){
var itemId = 4;
var payload;
var StringUrl = "https://someURL";
var boundary = '--' + uuidv4();
var files = file.load(1056); // getting the file
var fileContents = files.getContents(); // getting the content
var decodedStr = fromBaseUTF(fileContents); // conversion to Base64
var form_data = "{\"description\": \"Test Image\",\n\"ordering\": 1\n}";
// add the data field
payload = "\n" + boundary + "\n"
+ 'Content-Disposition: form-data; name=\"data\"\n\n'
+ form_data + "\n"
+ boundary + "\n"
+ 'Content-Disposition: form-data; name=\"image\"\n'
+ 'Content-Type: image/jpeg\n\n'
+ decodedStr + "\n"
+ boundary + "--\n\n";
log.debug("payload", payload);
var Header = {"Authorization": "Bearer " + token,
"Content-Type": "multipart/form-data; boundary=" + boundary
};
try {
var response = https.post({
url: StringUrl,
body: payload,
headers: Header
});
var newSFID = JSON.parse(response.body);
log.debug("Item Image creation", newSFID);
} catch (e) {
log.error({ title: 'Failed to submit file', details: (e.message || e.toString()) + (e.getStackTrace ? (' \n \n' + e.getStackTrace().join(' \n')) : '') });
log.error('ERROR Item Image Creation', JSON.stringify(e));
}
}
using postman, the image is correctly sent:
I am using a scheduled script, do you see what is wrong or is there a way to know what is send by netsuite?

There is an answer here that covers this: In NetSuite with SuiteScript 2.0 unable to send a file with HTTP POST request with a content-type multipart/form-data
what you missing is the Content-Transfer-Encoding header and you should be getting the content as Base64 so you shouldn't need to convert from UTF16 ( I could be wrong on that but I've never needed to)

Related

Google Drive API multipart upload file appears to be corrupted

public with sharing class uploadFileToGdrive {
public static void fileUploadHandler(List<ContentVersion> cvFileList) {
for (ContentVersion cvFile : cvFileList) {
system.debug('Loop');
// Get the content of the document
ContentVersion contentVersion = [SELECT Title, VersionData, FileType FROM ContentVersion WHERE ContentDocumentId = :cvFile.contentDocumentId ORDER BY CreatedDate DESC LIMIT 1];
Blob fileBody = contentVersion.VersionData;
String fileName = contentVersion.Title;
String fileType = contentVersion.FileType;
String boundary = '-------'+contentVersion.Id;
String header = 'Content-Type: multipart/related; boundary="' + boundary + '"\n' +
'Authorization: Bearer ' + [SELECT Access_Token__c FROM gDriveTokens__c][0].Access_Token__c + '\n' +
'Content-Length: ' + String.valueOf(fileBody.size()) + '\n' +
'\n';
String body = '--' + boundary + '\n' +
'Content-Type: application/json; charset=UTF-8\n' +
'\n' +
'{"name": "' + fileName + '"}\n' +
'--' + boundary + '\n' +
'Content-Type: '+MIMEHelper.getMIMEType(fileType)+'\n' +
'\n';
String requestBody = header + body + EncodingUtil.base64Encode(fileBody) + '\n--' + boundary + '--';
uploadFileToGdrive.uploadFileCallout(requestBody, boundary);
}
}
#future(callout=true)
public static void uploadFileCallout(String requestBody, String boundary) {
system.debug('Callout');
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart');
req.setHeader('Content-Type', 'multipart/related; boundary="' + boundary + '"');
req.setheader('Authorization','Bearer '+[SELECT Access_Token__c FROM gDriveTokens__c][0].Access_Token__c);
req.setBody(requestBody);
// Send the request
Http http = new Http();
HttpResponse res = http.send(req);
system.debug(res.getBody());
}
}
I was trying to upload a file from my salesforce system to my google drive using google drive api. The files are uploading. But when I download or try to open them, it shows this message.
Drive File Error

Access json array from navigator.camera.getPicture Cordova response

I am getting a response after I run a function that calls a cordova navigator.camera.getPicture() function. All works well and the response is below, however I can not access individual value-pairs
({"tagone" : "optimal", "datex" : "Thursday"})
I try this: r.response['tagone'] and just returns empty.
$scope.win = function (r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
$("#camLoader").hide();
$("#resultDiv").show();
$("#finalResult").append(r.response['tagone']);
//alert(r.response);
};

"Insufficient Permissions" Error with Google Appscripts

I get following error when I try to create draft using google appscripts
{
"error": {
"errors": [
{
"domain": "global",
"reason": "insufficientPermissions",
"message": "Insufficient Permission"
}
],
"code": 403,
"message": "Insufficient Permission"
}
}
I enabled GMAIL api service in resource --> Advanced google services. I am using the following end point to create the draft.
https://www.googleapis.com/gmail/v1/users/me/drafts
I am not sure if I need to enable any other api to make this work. Would appreciate any help to debug this issue
I am making the api as shown below:
function createDraft(tid,Subject,Body,fromEmail,toEmail,ccEmail) {
var boundary = "ABDADASFDSBCCCADSAD" + (new Date()).getTime().toString();
SendSubject = "Subject:" + Subject
raw = SendSubject + "\r\n" +
"From: " + fromEmail + "\r\n" +
"To: " + toEmail + "\r\n" +
"Cc: " + ccEmail + "\r\n" +
"Content-Type: multipart/alternative; boundary=" + boundary + "\r\n" + "\r\n" +
"--" + boundary + "\r\n" +
"Content-Type: text/html; charset=UTF-8" + "\r\n" +
"Content-Transfer-Encoding: quoted-printable" + "\r\n" + "\r\n" +
Body + "\r\n" + "\r\n" +
"--" + boundary + "--"
//var draftBody = Utilities.base64Encode(raw, Utilities.Charset.US_ASCII).replace(/\//g,'_').replace(/\+/g,'-')
var draftBody = Utilities.base64EncodeWebSafe(raw, Utilities.Charset.UTF_8)
var params = {method:"post",
contentType: "application/json",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken(), "Reply-To": "naveen#skedool.it"},
muteHttpExceptions:true,
payload:JSON.stringify({
"message": {
"raw": draftBody,
"threadId" : tid
}
})
};
var resp = UrlFetchApp.fetch("https://www.googleapis.com/gmail/v1/users/me/drafts", params);
//Logger.log(resp);
return resp
}
you need to give permission to your app to get the access,
you just need to add valued in SCOPES array
private static final String[] SCOPES = { GmailScopes.GMAIL_LABELS, GmailScopes.GMAIL_COMPOSE, GmailScopes.GMAIL_INSERT, GmailScopes.GMAIL_MODIFY, GmailScopes.MAIL_GOOGLE_COM};
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff())
.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
The error you are getting is related to the credentials. although you are sending a token, that token does not have access to Gmail.
In Apps script go to the menu "Resources > Advances Google Services"
There look for the Gmail service and enable it.
Then click on the link of the text "These services must also be enabled in the Google Developers Console."
It will open the Developer Console, and also there you have to enable the Gmail API.
After doing that, run your code again and it will ask for permission to access Gmail.
Now the token will have access to Gmail API.
Let me know if it didn't work for you.

Httprequest error. Help to make the correct request

I have example request:
curl https://upload.box.com/api/2.0/files/content \
-H "Authorization: Bearer ACCESS_TOKEN" \
-F filename=#FILE_NAME \
-F parent_id=PARENT_FOLDER_ID
My request returns an error missing_parameter","name":"parent","message":"'parent' is required".
This is my request:
String boundary = String.valueOf(DateTime.now().getTime());
String body = '------------' + boundary + '\r\n';
body +='Content-Disposition: form-data; name="FileName"; FileName="' + fileBody +'"\r\n';
body+='Content-Transfer-Encoding: base64\r\n';
if ((contentType == null) || (contentType == '')){contentType = 'application/octet-stream';}
body+='Content-Type: ' + contentType + '\r\n\r\n';
body+=EncodingUtil.base64Encode(fileBody);
body +='Content-Disposition: form-data; name="Parent"; \r\n';
body+='Content-Transfer-Encoding: base64\r\n';
if ((contentType == null) || (contentType == '')){contentType = 'application/octet-stream';}
body+='Content-Type: ' + contentType + '\r\n\r\n';
body+=0;
body+='\r\n------------' + boundary + '--';
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'multipart/form-data; boundary=----------' + boundary);
req.setHeader('Content-Length',String.valueof(body.length()));
req.setBody(body);
req.setHeader('Authorization', 'Bearer ' + accessToken.token__c);
req.setMethod('POST');
req.setEndpoint('https://upload.box.com/api/2.0/files/content');
Http http = new Http();
HttpResponse res = http.send(req);
It's asking for the ID of the folder you want to upload to.
try changing this line:
body +='Content-Disposition: form-data; name="Parent"; \r\n';
to:
body +='Content-Disposition: form-data; name="parent_id"; \r\n';
EDIT: though I have to ask, why are you sending the whole file body as the file name?

get 404 error by batch file upload via google-api-javascript-client library

I'm trying to upload whole folder to google drive.
I could successfully upload one file by one request.
But I met rateLimitExceed error while upload whole files.
So, I tried to use batch request.
Creating folders with batch request are successfully done.
but when I trying to upload file by batch request, it returns 404 error. ( Not Found )
Is this google drive's bug?
If so, should I do time delay for upload many files?
var boundary = '--314159265358979323846';
var delimiter = "\r\n--" + boundary + "\r\n";
var close_delim = "\r\n--" + boundary + "--";
var contentType = 'text/plain';
var metadata = {
'title': 'test1.txt',
'mimeType': contentType
};
var base64Data = btoa('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v2/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
var httpBatch = gapi.client.newHttpBatch();
httpBatch.add(request, {
callback: function(resp, rawResp){
console.log(rawResp);
}
});
httpBatch.execute(function(resp, rawResp){
console.log(rawResp)
});
error is here:
{"id":"1171148984","result":false}
{"gapiRequest":{"data":{"body":"--batch_YZmy6yr9vIk=_ABqi-xumfFQ=\r\nContent-Type: application/http\r\nContent-ID: <response-1171148984>\r\n\r\nHTTP/1.1 404 Not Found\r\nContent-Type: text/html; charset=UTF-8\r\nDate: Mon, 21 Oct 2013 07:53:20 GMT\r\nExpires: Mon, 21 Oct 2013 07:53:20 GMT\r\nCache-Control: private, max-age=0\r\nContent-Length: 9\r\n\r\nNot Found\r\n--batch_YZmy6yr9vIk=_ABqi-xumfFQ=--\r\n","headers":{"pragma":"no-cache","date":"Mon, 21 Oct 2013 07:53:20 GMT","server":"GSE","content-type":"multipart/mixed; boundary=batch_YZmy6yr9vIk=_ABqi-xumfFQ=","cache-control":"no-cache, no-store, max-age=0, must-revalidate","content-length":"349","expires":"Fri, 01 Jan 1990 00:00:00 GMT"},"status":200,"statusText":"OK"}}}
Uploading cannot be batched, please run the upload requests individually.

Resources