Azure blob SAS and Localized file name - java

I am using jclouds APIs to upload files to azure blob but I could not find any way to generate SAS using jClouds APIs so using Azure APIs to create SAS for specific blob.
Problem I am facing is the file which i am trying to upload has localized characters in its name e.g. "Jérôme" which I have to encode and decode at specific level while uploading, I am making sure that at the time of SAS generation i am passing decoded(actual) name of file but I am not able to access the same using generated SAS.
PS. I have tried different combinations of encoding and decoding string(file name) in upload and SAS generation but all in vain.
Error I am getting is "No such blob exist" and in some case "signature validation failure"
can anyone guide me with appropriate approach for the same?
Please let me know in case code snippet is required.
UPLOAD:
try (BlobStoreContext context = ContextBuilder.newBuilder("azureblob")
.credentials(this.storeName, this.storeKey)
.buildView(BlobStoreContext.class)) {
final BlobStore store = context.getBlobStore();
payload.getContentMetadata().setContentLength(blobSize);
final Blob blob = store.blobBuilder(URLEncoder.encode(blobName, StorageConstants.UNICODE_FORMAT)).payload(payload).build();
logger.debug("Uploading...");
store.putBlob(this.containerName, blob);
logger.debug("Uploaded...");
return true;
} catch (IOException e) {
logger.error("IOException while uploading file to azure blob", e);
return false;
} catch (Exception e) {
logger.error("Exception while uploading file to azure blob", e);
return false;
}
SAS Generation
String url = "";
try
{
final CloudBlobContainer container = getUploadContainer();
final CloudBlockBlob blob = container.getBlockBlobReference(blobName);
url = blob.getUri() +"?"+ blob.generateSharedAccessSignature(getPolicy(), null);
} catch (StorageException e) {
logger.error("Storage Exception was encounter in generateAttachmentSasUrl() :", e);
} catch (InvalidKeyException e) {
logger.error("Invalid Key Exception was encountered in generateAttachmentSasUrl() :", e);
} catch (URISyntaxException e) {
logger.error("Problems creating an URI was encounter in generateAttachmentSasUrl() : ", e);
}

Please test with jclouds 2.0.0-SNAPSHOT. Many issues with URL encoding were fixed as part of JCLOUDS-217.

Related

Kucoin Java SDK error KC-API-KEY not exists

Following their guide in usage here I couldn't get started.
The code:
KucoinClientBuilder builder = new KucoinClientBuilder()
.withApiKeyVersion(2)
.withBaseUrl("https://openapi-sandbox.kucoin.com")
.withApiKey("MyKey", "MySecret", "MyPass");
KucoinRestClient kucoinRestClient = builder.buildRestClient();
KucoinPrivateWSClient kucoinPrivateWSClient;
try {
kucoinPrivateWSClient = builder.buildPrivateWSClient();
KucoinPublicWSClient kucoinPublicWSClient = builder.buildPublicWSClient();
} catch (IOException e) {
e.printStackTrace();
}
builder.buildPrivateWSClient() throws an exception with this message:
KucoinApiException{code='400003', message='KC-API-KEY not exists'}
I copied the Api Key and Secret and pass from the api page
What am I missing here? Why the KC-API-KEY does not exist?
The "sandbox" account is different than the original account.
Its domain is different and you need to register in the sandbox version of the website here

Upload image to AWS S3 bucket and serve that image using Amazon CloudFront signed urls

I need to upload an image to AWS S3 bucket and serve that image through Amazon CloudFront. Currently what I am doing is uploading the image to S3 with the specified file name. After uploading using the file name I am generating the CloudFront signed url. I am making two separate calls which I want to avoid. Is there a way where in I can directly upload file to S3 via CDN and get the CloudFront url for that file via java spring boot. Any advice is appreciated.
My current code is as follows. I am uploading multiple files at once. In that case getting CloudFront signed url could be trickier I believe or is there any way to get that in multiple upload as well ?
upload to s3
public void uploadMultipleFiles(final List<File> files) {
final TransferManager transferManager = TransferManagerBuilder.standard().withS3Client(amazonS3).build();
try {
final MultipleFileUpload xfer = transferManager.uploadFileList(bucketName, null, new File("."), files);
xfer.waitForCompletion();
} catch (InterruptedException exception) {
//do something
} catch (AmazonServiceException exception) {
//do something
}
}
Get signed url from CDN
public String getCdnUrl(final String s3ObjectKey) {
final File privateKeyFile = new File(keyPath);
String cdnUrl = null;
try {
cdnUrl = CloudFrontUrlSigner.getSignedURLWithCannedPolicy(Protocol.https, distributionDomain,
privateKeyFile, s3ObjectKey, accessKey, DateUtils.parseISO8601Date("2021-06-20T22:20:00.000Z"));
} catch (InvalidKeySpecException exception) {
} catch (IOException ioException) {
}
return cdnUrl;
}

send message to single device using Firebase cloud with Java

I'm trying to send messages to single devices using their token from a Java application. I'm using the Firebase Admin SDK. Below is what I have
FileInputStream serviceAccount = null;
try {
serviceAccount = new FileInputStream("google-services.json");
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
FirebaseOptions options = null;
try {
options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://MYPROJECTID.firebaseio.com/")
.build();
} catch (IOException e1) {
e1.printStackTrace();
}
FirebaseApp.initializeApp(options);
String registrationToken = "MYDEVICETOKEN";
// See documentation on defining a message payload.
Message message = Message.builder().putData("time", "2:45").setToken(registrationToken)
.build();
// Send a message to the device corresponding to the provided
// registration token.
String response = null;
try {
response = FirebaseMessaging.getInstance().sendAsync(message).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
But I get the following exception
java.io.IOException: Error reading credentials from stream, 'type' field not specified.
What am I doing wrong here?
Click on Generate new private key button.
The error means that your google-services.json file contains invalid data. GoogleCredentials class expects your file to have a type property, but it's not there.
Brief googling gave me this post regarding very similar problem. It says:
From the API Manager, just create select "Create credentials" >
"Service Account key" and generate a new key for the Service
that is associated to your Google Play account.

Accessing web API protected by Azure AD using a web app client

Can someone please explain me how to access the protected web api using a web app client?
I am trying something mentioned here in the following link. But I am always getting
The provided access grant is invalid or malformed.
https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx
Here is the code i am using for java
AuthenticationResult result = null;
try {
final Future<AuthenticationResult> resultFuture = context.acquireTokenByAuthorizationCode(
code, new URI(redirectUri), new ClientCredential(clientId, clientSecret), RESOURCE_GRAPH_API, null);
result = resultFuture.get();
} catch (InterruptedException | ExecutionException e) {
LOG.info("Failed to obtain access token: " + e.getMessage());
} catch (URISyntaxException e) {
}

Trasferring files and data with Jersey

I'm trying to develop some rest services with Jersey to upload and download files (something like a file manager). If my services produce/consume only File class as "application/octet-stream", like in the code below, they work.
#GET
#Produces("application/octet-stream")
public File getFile(String id) {
try {
File file = new File(System.getProperty("user.home"), id);
return file;
} catch (FileNotFoundException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
But if I try to transfer a custom object that contains a File field and some other data (FileEnvelope in the sample) I obtain an error.
#GET
#Produces("application/octet-stream")
public FileEnvelope getXml(String id) {
try {
File file = new File(System.getProperty("user.home"), id);
FileEnvelope fileEnvelope = new FileEnvelope(file, "text");
return fileEnvelope;
} catch (FileNotFoundException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
The error is
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class com.mycompany.restdemo.FileEnvelope, and Java type class com.mycompany.restdemo.FileEnvelope, and MIME media type application/octet-stream was not found
Where I'm wrong? Is this the right way to manage this case? My client could not be a "Jersey client".
Jersey has no idea how to serialize your domain object into an octet-stream unless you tell it how. In this case if you want to include extra information beyond the file data you should consider how the client should be expected to read it. You could:
Embed the information directly in the octet stream by creating your own MessageBodyWriter. The client would need to know where to look for this information in the resulting file.
Include the information as part of the HTTP response header using ResponseBuilder. The client would just need to know which response headers to check for the information.
You can send different types of data in one message using multipart/* media types. For example this article shows how: http://aruld.info/handling-multiparts-in-restful-applications-using-jersey/

Categories

Resources