I have an Email Web Service - working ok - and now I need to add attachment.
1.How do I write the #FormParam in my post method to receive byte[] ?
2.How do I write my bean the addParam to add the file?
My bean is like this:
public String sendEmail() throws IOException{
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest req = (HttpServletRequest) context.getExternalContext().getRequest();
String ip = req.getRemoteAddr();
String conteudo = "é ô ç $ & / { [";
List<byte[]> att = new ArrayList<byte[]>();
String request = "myURI";
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(request);
method.getParams().setContentCharset("utf-8");
method.addParameter("conteudo", conteudo);
method.addParameter("ip", ip);
return "sendEmail ok";
}
My POST Method is like this:
#POST
#Path("/sendEmail")
#Consumes({"application/json","application/x-www-form-urlencoded",})
public String sEmail(#FormParam("conteudo") String conteudo, #FormParam("ip") String ip)throws MessagingException {
String de = "de#mail.com.br";
String para = "para#rmail.com.br";
String cc = "";
String cco = "";
String titulo = "Email test";
String conteudo = "conteudo";
try {
Email email = new SimpleEmail();
email.setHostName("smtp....");
email.setSmtpPort(25);
email.setStartTLSEnabled(true);
email.setFrom(de);
email.addTo(para);
email.setSubject(titulo);
email.setMsg(conteudo);
if (!cc.equals("")){
email.addCc(cc);
}
if (!cco.equals("")){
email.addBcc(cco);
}
email.send();
} catch (EmailException e) {
Logger.getLogger(Mail.class.getName()).log(Level.SEVERE, null, e.getMessage());
}
I use JavaMail 1.4.
I encoded to base64, then I put all the files into a String separated with ;
In the web service first I split the String and then I decoded from base64.
Related
I am a salesforce developer, our company are planning to extend the service for global users, so we decided to use google translate to improve our customers' experience.
I have read the google api document, however, we met an issue when requesting GCP access token, the tutorial google provided in document which supports different languages, like java, c#, python etc. Since we are suing apex (a type of salesforce platform script), we weren't able to use your library to get GCP token.
Instead, we also checked "OAuth 2.0 for Server Accounts", unfortunately, neither worked from me.
Is there any suggestions?
I got token by below code, and the error I met was caused by special characters encode.
public with sharing class SwitchLanguageByGoogleAPIController {
private static final String ENDPOINT = '**';
private static final String TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token';
private static final String SCOPE = 'https://www.googleapis.com/auth/cloud-platform';
private static final String PROJECT_ID = '**';
private static final String GLOSSARY_ID = '88';
private static final String LOCATION_ID = 'us-central1';
private static final String CLIENT_SECRET = '**';
private static final String PRIVATE_KEY = '**';
private static final String CLIENT_EMAIL = '**';
public static void translateByGlossary() {
Token token = getToken();
HttpRequest request = new HttpRequest();
request.setHeader('Content-Type', 'text/plain');
request.setEndpoint(ENDPOINT + PROJECT_ID + '/locations/' + LOCATION_ID + ':translateText?access_token=' + token.access_token);
request.setMethod('POST');
String contents = 'Personal Information, Middle Name e, first First Name';
String sourceLanguageCode = 'en';
String targetLanguageCode = 'zh';
request.setBody('{"sourceLanguageCode":"' + sourceLanguageCode + '","targetLanguageCode":"' + targetLanguageCode + '","contents":"'+ contents +'","glossaryConfig":{"glossary":"projects/' + PROJECT_ID +'/locations/' + LOCATION_ID + '/glossaries/' + GLOSSARY_ID + '"}}');
HTTP http = new HTTP();
HttpResponse reponse = http.send(request);
System.debug(reponse.getBody());
}
private static Token getToken() {
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
//Making the call out
req.setEndpoint(TOKEN_ENDPOINT);
req.setMethod('POST');
req.setHeader('Content-Type','application/x-www-form-urlencoded');
string URLEncodedGrantType = encodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer','UTF-8');
string jwtSigned = generateJWT();
req.setBody('grant_type='+URLEncodedGrantType+'&assertion='+jwtSigned);
res = http.send(req);
system.debug('Response : '+res.getBody());
return (Token)JSON.deserialize(res.getBody(), Token.Class);
}
private static String generateJWT() {
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
String JWTHeader = '{"typ":"JWT","alg":"RS256"}';
String Base64EncodedJWTHeader = EncodingUtil.base64Encode(Blob.valueOf(JWTHeader));
long issued_at = datetime.now().getTime()/1000;
long expires_at = datetime.now().addHours(1).getTime()/1000;
JWTClaimSet claimSet = new JWTClaimSet();
claimSet.iss = CLIENT_EMAIL;
claimSet.scope = SCOPE;
claimSet.aud = TOKEN_ENDPOINT;
claimSet.iat = issued_at;
claimSet.exp = expires_at;
String strClaimSetJSON = JSON.Serialize(claimSet);
String Base64EncodedClaimset = EncodingUtil.base64Encode(Blob.valueOf(strClaimSetJSON));
system.debug('Base64 Encoded Claimset::'+Base64EncodedClaimset);
Base64EncodedClaimset = PerformPostBase64Encode(Base64EncodedClaimset);
system.debug('persorm post Claimset::'+Base64EncodedClaimset);
string Base64EncodedString = Base64EncodedJWTHeader + '.' + Base64EncodedClaimset;
String algorithmName = 'RSA-SHA256';
Blob privateKey = EncodingUtil.base64Decode(PRIVATE_KEY);
Blob input = Blob.valueOf(Base64EncodedString);
Blob Blobsign = Crypto.sign(algorithmName, input , privateKey);
String base64EncodedSignature = EncodingUtil.base64Encode(Blobsign);
base64EncodedSignature = PerformPostBase64Encode(base64EncodedSignature);
system.debug('Base 64 encoded signature ::'+base64EncodedSignature );
system.debug('Encoded assertion : ' + Base64EncodedString+'.'+base64EncodedSignature);
string URLEncodedUTF8Assertion = encodingUtil.urlEncode(Base64EncodedString+'.'+base64EncodedSignature,'UTF-8');
return URLEncodedUTF8Assertion;
}
public static String PerformPostBase64Encode(String s)
{
s = s.Replace('+', '-');
s = s.Replace('/', '_');
s = s.Split('=')[0];
return s;
}
public class JWTClaimSet
{
public string iss {get;set;}
public string scope {get;set;}
public string aud {get;set;}
public Long exp {get;set;}
public Long iat {get;set;}
}
private class Token{
private String access_token;
private String token_type;
private String expires_in;
}
}
using postman, for a GET request with header values for user name and password
and successfully hitting a rest service and getting response 200.
But when trying to access same request by java code using spring RestTemplate getting 401-unauthorized issue.
this is the code
final String uri = "http://<host>:<port>/services/arecord";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("username", "admin");
String password = "admin";
map.add("password", password);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
RestTemplate restTemplate = new RestTemplate();
try {
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET,
new HttpEntity(createHeaders("admin", "admin")), String.class);
String body = response.getBody();
} catch (HttpClientErrorException e) {
logger.info("****** ERROR *********** " + e.getMostSpecificCause());
return true;
}
I haven't tested it, but try something like this:
final String uri = "http://<host>:<port>/services/arecord";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("username", "admin");
headers.set("password", "admin");
HttpEntity entity = new HttpEntity(headers);
RestTemplate restTemplate = new RestTemplate();
try {
ResponseEntity<String> response = restTemplate.exchange(
uri, HttpMethod.GET, entity, String.class);
String body = response.getBody();
} catch (HttpClientErrorException e) {
logger.info("****** ERROR *********** " + e.getMostSpecificCause());
return true;
}
I'm following the api's guide about resumable uploads.
I managed to get a response after step 1 ("create the video"),
with a uri and a upload_link.
About the second part, things are not as clear.
It only says which headers should I sent, but there are two things I don't get,
first - where do I need to put the "upload_link"?
Should the call be like this:
/me/{upload_link}? (of course im also adding the access token, etc)
second, what about the actual file? I guess i should send it in the same method, but how? No word about it.
This is the code for the PATCH request:
public string UploadPatch(
string uploadlink,
string method)
{
var headers = new WebHeaderCollection()
{
{ "Tus-Resumable", "1.0.0" },
{ "Upload-Offest", "0" }
};
method = method.ToUpper();
string body = "";
string contentType = "application/offset+octet-stream";
return Helpers.HTTPUpload(uploadlink, method, headers, body, contentType);
}
And HTTPUpload():
public static string HTTPPatch(string url, string method,
WebHeaderCollection headers, string payload,
string contentType)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.CreateHttp(url);
if (Proxy != null) request.Proxy = Proxy;
request.Headers = headers;
request.Method = method;
request.Accept = "application/vnd.vimeo.*+json; version=3.1";
request.ContentType = contentType;
request.KeepAlive = false;
if (!String.IsNullOrWhiteSpace(payload))
{
var streamBytes = Helpers.ToByteArray(payload);
request.ContentLength = streamBytes.Length;
Stream reqStream = request.GetRequestStream();
reqStream.Write(streamBytes, 0, streamBytes.Length);
reqStream.Close();
}
HttpWebResponse response = (HttpWebResponse)(request.GetResponse());
Debug.WriteLine(((HttpWebResponse)response).StatusDescription);
var dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
Debug.WriteLine(String.Format("Response from URL {0}:", url), "HTTPFetch");
Debug.WriteLine(responseFromServer, "HTTPFetch");
return responseFromServer;
}
Thanks
The upload_link is the URL where you upload the video to. In other words, make your call to the https://[...].cloud.vimeo.com/upload?[...] URL instead of the https://api.vimeo.com host that is used for other API requests.
Additionally, when you make a request to that cloud.vimeo.com upload_link, only provide the required headers as specified in the documentation.
https://developer.vimeo.com/api/upload/videos#resumable-approach
The code is VB.Net, but you can change to C#
'Imports / use these classes
'Imports System.Net
'Imports Newtonsoft.Json
'Imports System.IO
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
'Receive the video from File Upload
If Not IsNothing(fuVideo.PostedFile) Then
'You will need this for SSL
System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType.Tls Or (SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls12))
'Path to save the video Save
Dim vFilePath As String = Server.MapPath("App_data/Videos")
Dim vFileNameAndPath As String = vFilePath & "/" & fuVideo.PostedFile.FileName
'Save Video
fuVideo.PostedFile.SaveAs(vFileNameAndPath)
'Get the size
Dim vSize As String = New FileInfo(vFileNameAndPath).Length()
'Vimeo URL
Dim vVimeURL As String = "https://api.vimeo.com/me/videos"
Dim wc As WebClient = New WebClient()
wc.Headers.Clear()
wc.Headers.Add("Authorization", "bearer XXXXXXXXXXXXXXXXX") 'Use your App Code
wc.Headers.Add("Content-Type", "application/json")
wc.Headers.Add("Accept", "application/vnd.vimeo.*+json;version=3.4")
wc.Encoding = System.Text.Encoding.UTF8
'txtName is a text box, so you can give a Title to the Video
Dim vData As String = "{ ""upload"": {""approach"": ""tus"",""size"": """ & vSize & """ }, ""name"" : """ & txtName.Text & """ }"
Dim vimeoTicket = JsonConvert.DeserializeObject(wc.UploadString(vVimeURL, "POST", vData))
wc.Headers.Clear()
wc.Headers.Add("Content-Type", "application/offset+octet-stream")
wc.Headers.Add("Accept", "application/vnd.vimeo.*+json;version=3.4")
wc.Headers.Add("Tus-Resumable", "1.0.0")
wc.Headers.Add("Upload-Offset", "0")
Dim vupload_link As String = vimeoTicket("upload")("upload_link").Value 'Json from Vimeo has the upload_link
Dim vResponse As Byte() = wc.UploadFile(vupload_link, "PATCH", vFileNameAndPath)
Response.Write(System.Text.Encoding.Unicode.GetString(vResponse)) ' If everething is ok, vResponse is Nothing
End If
Catch ex As Exception
ltrErro.Text = "Error"
End Try
End Sub
for this may look at the sample code below:-
I am using a nuget library vimeo-dot-net also at https://github.com/mfilippov/vimeo-dot-net, this has a wrapper built around upload, delete etc.
public ActionResult UploadChapterVideoVimeo(HttpPostedFileBase file, string productID = "")
{
if (file != null){
var authCheck = Task.Run(async () => await vimeoClient.GetAccountInformationAsync()).Result;
if (authCheck.Name != null)
{
BinaryContent binaryContent = new BinaryContent(file.InputStream, file.ContentType);
int chunkSize = 0;
int contenetLength = file.ContentLength;
int temp1 = contenetLength / 1024;
if (temp1 > 1)
{
chunkSize = temp1 / 1024;
chunkSize = chunkSize * 1048576;
}
else
{ chunkSize = chunkSize * 1048576; }
binaryContent.OriginalFileName = file.FileName;
var d = Task.Run(async () => await vimeoClient.UploadEntireFileAsync(binaryContent, chunkSize, null)).Result;
vmodel.chapter_vimeo_url = "VIMEO-" + d.ClipUri;
}
return RedirectToAction("ProductBuilder", "Products", new { productId = EncryptedProductID, message = "Successfully Uploaded video", type = 1 });
}
}
catch (Exception exc)
{
return RedirectToAction("ProductBuilder", "Products", new { productId = EncryptedProductID, message = "Failed to Uploaded video " + exc.Message, type = 0 });
}
}
return null; }
I am using Spring 4 latest, and I generally have no problem writing RESTful controllers. There is a legacy web-app, which is using java.net.HTTPUrlConnection to do a multi-part upload. There are 3 pieces of data we are uploading:
1 is a PDF file, and we have the bytes, then the other two pieces of data are just 2 string fields.
First let me show you the Spring REST controller to accept the data:
#RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data")
public #ResponseBody boolean saveData(#RequestPart(value = "field1") String field1, #RequestPart(value = "field2") String field2, #RequestParam(value = "pdfbytes") String pdfbytes)
{
System.out.println("saveData: field1=" + field1);
System.out.println("saveData: field2=" + field2);
System.out.println("saveData: pdfbytes=" + pdfbytes);
boolean response = true;
return response;
}
The code in front-end, for sending the data using 'java.net.HttpURLConnection'
looks like this:
String boundary = MultiPartFormOutputStream.createBoundary();
URL uploadDocumentUrl = new URL(protocol + "://" + host + UPLOAD_EDITED_DOCUMENT);
HttpURLConnection urlConn = (HttpURLConnection) MultiPartFormOutputStream.createConnection(uploadDocumentUrl);
urlConn.setRequestProperty("Content-Type", MultiPartFormOutputStream.getContentType(boundary));
urlConn.setRequestProperty("Connection", "Keep-Alive");
urlConn.setRequestProperty("Cache-Control", "no-cache");
urlConn.setRequestProperty("User-Agent", userAgent);
urlConn.setRequestMethod("POST");
MultiPartFormOutputStream out = new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary);
String pdfbytes= getEncodedDocument(pdf);
out.writeField("field1", field1);
out.writeField("field2", field2);
out.writeField("pdfbytes", pdfbytes);
out.close();
int responseCode = urlConn.getResponseCode();
String responseMessage = urlConn.getResponseMessage();
"MultiPartFormOutputStream" is a custom object that was created to send data via HttpUrlConnection, it's pretty standard code. I do trust it at this time.
So, based on how we are sending the data, do I need to change the Controller to do anything different, or does that look ok?
Now here is the code, that I am using to Unit Test that controller:
#Test
public void testMockUpload() throws Exception
{
// Load resource being uploaded
byte[] pdfbytes = getByteArrayFromFile(FILENAME);
MockMultipartFile firstFile = new MockMultipartFile("field1", "", "text/plain", "field1 data".getBytes());
MockMultipartFile secondFile = new MockMultipartFile("field2", "", "text/plain", "field2 data".getBytes());
MockMultipartFile jsonFile = new MockMultipartFile("pdfbytes", "", "text/plain", pdfbytes);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.fileUpload(BASE_URL + "/save").file(firstFile).file(secondFile).file(jsonFile)
.with(user(USERNAME).roles("role1", "role2")).contentType(MediaType.MULTIPART_FORM_DATA_VALUE);
this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk());
}
And the error I get back now, is:
org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException
which I am looking into. If I need to make any changes on how I need to create my test, I am very open to that. Eventually, I will get everything to sync up between the sending code, the receiving controller, and the unit test.
Thanks in advance! As usual, if there is any other data, or information, I can provide, please let me know. Thanks!
To upload one file you would define the RequestParam type as org.springframework.web.multipart.MultipartFile;
#RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data")
public #ResponseBody boolean saveData(#RequestParam(value = "file") MultipartFile file)
{
return response;
}
For Multiple files I'd try creating a Wrapper form:
public class UploadForm{
private List<MultipartFile> files;
}
Bind to this in the controller:
#RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data")
public #ResponseBody boolean saveData(#ModelAttribute uploadForm)
{
return response;
}
and then use Spring's support for indexed fields to bind to a collection:
Test:
MockMultipartFile firstFile = new MockMultipartFile("files[0]", "", "text/plain", "field1 data".getBytes());
MockMultipartFile secondFile = new MockMultipartFile("files[1]", "", "text/plain", "field2 data".getBytes());
MockMultipartFile jsonFile = new MockMultipartFile("files[2]", "", "text/plain", pdfbytes);
Client:
out.writeField("files[0]", file1Bytes);
out.writeField("files[1]", file2Bytes);
...
I am trying to grasp how Play framework handles its web service calls.
This is Foursquare's directions (after 1 and 2):
Your server will make a request for
https://foursquare.com/oauth2/access_token
?client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&grant_type=authorization_code
&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
&code=CODE
The response will be JSON
{ access_token: ACCESS_TOKEN }
And this is my code:
public static Result index() {
String base = "http://foursquare.com/oauth2/authenticate";
String clientId = "?client_id=***";
String responseType = "&response_type=code";
String redirectUri = "&redirect_uri=http://localhost:9000/code";
return redirect(base + clientId + responseType + redirectUri);
}
public static Result code() {
String base = "http://foursquare.com/oauth2/access_token";
String clientId = "?client_id=***";
String clientsecret = "&client_secret=***";
String grantType = "&grant_type=authorization_code";
String redirectUri = "&redirect_uri=http://localhost:9000/json";
String code = "&code=" + request().getQueryString("code");
return redirect(base + clientId + clientsecret + grantType
+ redirectUri + code);
}
There are two things I am curios about:
1) I am redirected to a page with the access token displayed on screen:
URL: https://foursquare.com/oauth2/access_token?client_id=***&client_secret=***&grant_type=authorization_code&redirect_uri=http://localhost:9000/json&code=***
With this displayed:
{"access_token":"***"}
I would have expected to be redirected to http://localhost:9000/json as that was the redirect uri...
2) How do I grab the access token? I have tried using the asynchronous web service calls vis http://www.playframework.com/documentation/2.2.x/JavaWS but I cannot make them work.
My attempt:
String feedUrl = base + clientId + clientsecret + grantType
+ redirectUri + code;
final Promise<Result> resultPromise = WS.url(feedUrl).get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok("Feed title:" + response.asJson().findPath("access_token").asText());
}
}
);
return resultPromise;
This gives me an exception: [ConnectException: Connection refused: no further information: foursquare.com/107.23.103.139:80 to http://foursquare.com/oauth2/access_token]
All help is appreciated greatly!
This is the class that I made to get the foursquare access_token and submit a new search to foursquare:
public class Application extends Controller {
static final String HOST_AUTHENTICATE = "foursquare.com/oauth2/authenticate";
static final String HOST_ACCESS_TOKEN = "https://www.foursquare.com/oauth2/access_token";
static final String CLIENT_ID = "***";
static final String REDIRECT_URI = "http://localhost:9000/code";
static final String CLIENT_SECRET = "***";
static final String GRANT_TYPE = "authorization_code";
static final String RESPONSE_TYPE = "code";
static final String FOURSQUARE_API_FRIENDS = "https://api.foursquare.com/v2/users/self/friends";
public static Result index() {
String uri = new URIBuilder().setScheme("https").setHost(HOST_AUTHENTICATE)
.setParameter("client_id", CLIENT_ID).setParameter("response_type", RESPONSE_TYPE)
.setParameter("redirect_uri", REDIRECT_URI).toString();
return redirect(uri);
}
public static Promise<Result> code() {
WSRequestHolder authenticate = WS.url(HOST_ACCESS_TOKEN).setQueryParameter("client_id", CLIENT_ID)
.setQueryParameter("client_secret", CLIENT_SECRET).setQueryParameter("grant_type", GRANT_TYPE)
.setQueryParameter("redirect_uri", REDIRECT_URI)
.setQueryParameter("code", request().getQueryString("code").toString());
final Promise<Result> resultPromise = authenticate.get().flatMap(new Function<WS.Response, Promise<Result>>() {
public Promise<Result> apply(WS.Response response) {
JsonNode json = response.asJson();
return WS.url(FOURSQUARE_API_FRIENDS).setQueryParameter("oauth_token", json.findPath("access_token").asText())
.setQueryParameter("v", "20131108").get().map(new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asJson());
}
});
}
});
return resultPromise;
}
}