'How to generate and preview a presigned url of a file in jsf?
I am trying to preview any type of file such as image,pdf,doc,odt,xlsx,csv,text etc in my web app using jsf.
My flow of code:
- Generating a presigned url using aws s3 bucket, java sdk.
- Then passing this to google doc or microsoft API to preview.
Code of generating presigned url
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Duration;
import java.util.Date;
import java.util.logging.Level;
import org.apache.tika.Tika;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetUrlRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;
.........
.........
.........
public void awsService(){
AwsCredentialsProvider acp = StaticCredentialsProvider.create(AwsBasicCredentials.create("AccesId", "Key"));
String fileName = "dummy.pdf";
String bucketName = "ViewerBucket";
File file = new File("some/path/to/file/dummy.pdf");
if (file.exists()) {
//uploading file before getting pre-signed url
PutObjectResponse response = s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(fileName)
.contentType(tika.detect(file)).contentDisposition("attachment; filenName=\"" + fileName + "\"").build(),
RequestBody.fromFile(file)); //incontentDisposition tried with attachment/inline
S3Presigner presigner = S3Presigner.builder()
.credentialsProvider(acp)
.region(Region.US_EAST_1)
.build();
signBucket(presigner, bucketName, fileName, file, new Tika().detect(file));
getPresignedUrl(presigner, bucketName, fileName);
}
}
public void getPresignedUrl(S3Presigner presigner, String bucketName, String keyName) {
try {
GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(bucketName).key(keyName).build();
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofMinutes(10))
.getObjectRequest(getObjectRequest).build();
// Generate the presigned request
PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest);
// Log the presigned URL
System.out.println("Presigned URL: " + presignedGetObjectRequest.url()); //This url also has same issue with image and pdf as mentioned above
} catch (Exception e) {
e.printStackTrace();
}
}
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.16.60</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
and
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
I tried many solutions and many ways but preview is not working in browser as well as in code.
I edited my question now I am getting url and pdf is opening in browser but when I passing to google doc showing as preview not available and when passing in microsoft doc showing as file not found. but the same pdf link is previewing in browser.
Please guide me or tell me where am I wrong. Anyhelp will be appreciated Thanks alot in advance.
working with Jsf 2 and primefaces 6.2
Solution 1:[1]
After a hard and searching Got the solution
public String previewFile;
public void preview(String path, String fileName) {
try {
//file path
path += fileName;
File file = new File(path.toString());
if (file.exists()) {
fileType = new Tika().detect(file);
//aws bucket name
String bucketName = "bucketName";
//aws credentials if we not define here it will search by default at lcoation .aws/credentials
AwsCredentialsProvider acp = StaticCredentialsProvider
.create(AwsBasicCredentials.create("Access key", "Secret key"));
//upload file to aws account
upload(acp, bucketName, fileName, file);
//generating presigned url Thisis a public url
getUrl(acp, bucketName, fileName);
//public url opening in browser
PrimeFaces.current().executeScript("window.open('" + previewFile + "', '_blank');");
} else {
Message.addMessage("File does not exist", Message.severity.ERR);
}
} catch (IOException | AwsServiceException | SdkClientException e) {
e.printStackTrac();
} catch (Exception e) {
e.printStackTrac();
}
}
//uplaod file to aws bucket
public void upload(AwsCredentialsProvider acp, String bucketName, String fileName, File file) {
S3Client s3Client = S3Client.builder().credentialsProvider(acp).region(Region.US_EAST_1).build();
s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(fileName)
.contentType(fileType).contentDisposition("inline; filenName=\"" + fileName + "\"")
.build(),
RequestBody.fromFile(file));
s3Client.close();
}
//getting public url
public void getUrl(AwsCredentialsProvider acp, String bucketName, String keyName) {
try {
S3Presigner presigner = S3Presigner.builder()
.credentialsProvider(acp)
.region(Region.US_EAST_1)
.build();
GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(bucketName).key(keyName).build();
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofMinutes(10))
.getObjectRequest(getObjectRequest).build();
PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest);
String url = presignedGetObjectRequest.url().toString();
presigner.close();
if (fileType.startsWith("image/") || fileType.startsWith("application/pdf")) {
this.previewFile = url;
} else {
this.previewFile = "https://view.officeapps.live.com/op/embed.aspx?src=" + URLEncoder.encode(url, "UTF-8");
}
} catch (Exception e) {
e.printStackTrac();
}
}
Mainly I forgot to encode the url while passing in office API's.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mohammedsameer Inamdar |