Download file to local and upload to s3 / Share single signed URL

 https://github.ford.com/PBIRJE/Signed-URL-Solution-Approach/wiki

https://github.ford.com/PBIRJE/Signed-URL-Solution-Approach/wiki

package com.ford.ierp.epayableseuservice.controller;
import java.io.IOException;
import javax.validation.Valid;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import com.ford.ierp.epayableseuservice.constant.Constant;
import com.ford.ierp.epayableseuservice.model.ErrorResponse;
import com.ford.ierp.epayableseuservice.service.PdfDownloadPOCService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
@RefreshScope
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
@RequestMapping(path = "/pdfDownload")
public class PdfDownloadPOCCOntroller {
@Autowired
PdfDownloadPOCService pdfDownloadPOCService;
@ApiOperation(authorizations = {
@Authorization(value = "oauth2", scopes = {}) }, value = "Get PDF file", notes = "Returns a Zip file for the given Request Param")
@ApiResponses({ @ApiResponse(code = 200, message = "OK", response = StreamingResponseBody.class),
@ApiResponse(code = 400, message = "Bad request", response = ErrorResponse.class),
@ApiResponse(code = 401, message = "Unauthorized", response = ErrorResponse.class),
@ApiResponse(code = 403, message = "Forbidden", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class),
@ApiResponse(code = 415, message = "Method Not Implemented", response = ErrorResponse.class),
@ApiResponse(code = 429, message = "Too Many Requests", response = ErrorResponse.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = ErrorResponse.class),
@ApiResponse(code = 0, message = "All Errors", response = ErrorResponse.class) })
@GetMapping("/single")
public ResponseEntity<StreamingResponseBody> fetchSinglePDF(@RequestParam(required = true) @Valid @Size(min = 1, max = 20) @Pattern(regexp = Constant.COMMON_REGEX) String documentId) throws IOException {
return ResponseEntity.ok().header("Content-Disposition", "attachment; filename=\"PDFFile.zip\"").body(out -> {
pdfDownloadPOCService.generatePDF(documentId, out);
});
}
@ApiOperation(authorizations = {
@Authorization(value = "oauth2", scopes = {}) }, value = "Get PDF file", notes = "Returns a Zip file for the given Request Params")
@ApiResponses({ @ApiResponse(code = 200, message = "OK", response = StreamingResponseBody.class),
@ApiResponse(code = 400, message = "Bad request", response = ErrorResponse.class),
@ApiResponse(code = 401, message = "Unauthorized", response = ErrorResponse.class),
@ApiResponse(code = 403, message = "Forbidden", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class),
@ApiResponse(code = 415, message = "Method Not Implemented", response = ErrorResponse.class),
@ApiResponse(code = 429, message = "Too Many Requests", response = ErrorResponse.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = ErrorResponse.class),
@ApiResponse(code = 0, message = "All Errors", response = ErrorResponse.class) })
@GetMapping("/multiple")
public ResponseEntity<StreamingResponseBody> fetchMultiplePDFs(@RequestParam(required = true) @Valid @Size(min = 1, max = 100) @Pattern(regexp = Constant.COMMON_REGEX) String documentId) throws IOException {
return ResponseEntity.ok().header("Content-Disposition", "attachment; filename=\"PDFFile.zip\"").body(out -> {
pdfDownloadPOCService.generatePDF(documentId,out);
});
}
}
package com.ford.ierp.epayableseuservice.serviceimpl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;
import com.ford.ierp.epayableseuservice.service.PdfDownloadPOCService;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class PdfDownloadPOCServiceImpl implements PdfDownloadPOCService{
@Autowired
@Qualifier("Epayables")
WebClient webClient;
@Value("${s4.pdf.download.url}")
private String s4PdfDownloadUrl;
@Override
public void generatePDF(String documentId, OutputStream out) throws IOException {
String s4Url = s4PdfDownloadUrl;
if(documentId.contains(",")) {
documentId = documentId.replace("," , "|");
}
@SuppressWarnings("deprecation")
ResponseEntity<byte[]> response1 = webClient.get().uri(UriComponentsBuilder.fromHttpUrl(s4Url).build(documentId)).exchange()
.flatMap(result -> result.toEntity(byte[].class)).block();
log.info("S4 URL : {}", s4Url);
byte[] arr = response1.getBody();
ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ZipInputStream zis = new ZipInputStream(bais);
var zos = new ZipOutputStream(out);
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len;
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
bos.close();
byte[] entries = bos.toByteArray();
ZipEntry newentry = new ZipEntry(zipEntry.getName());
System.out.println(newentry.getName());
zos.putNextEntry(newentry);
zos.write(entries);
zos.closeEntry();
}
zos.close();
zis.close();
}
}
package com.ford.ierp.epayableseuservice.serviceimpl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.HttpMethod;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CreateBucketRequest;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.ford.ierp.epayableseuservice.configuration.AwsS3Config;
//import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import com.ford.ierp.epayableseuservice.service.SignedUrlService;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class SignedUrlServiceImpl implements SignedUrlService {
@Autowired
@Qualifier("Epayables")
WebClient webClient;
@Value("${s4.pdf.download.url}")
private String s4PdfDownloadUrl;
@Value("${s3.bucket}")
private String bucketName;
@Autowired
@Qualifier("AmazonS3")
AmazonS3 s3Client;
@Autowired
AwsS3Config awsS3Config;
public AmazonS3 getAmazonS3() {
return awsS3Config.getAmazonS3();
}
@Override
public ResponseEntity<Object> getSignedUrl(String documentId) throws IOException {
String s4Url = s4PdfDownloadUrl;
String fileName = null;
String signedUrl = null;
if(documentId.contains(",")) {
documentId = documentId.replace("," , "|");
}
@SuppressWarnings("deprecation")
ResponseEntity<byte[]> response = webClient.get().uri(UriComponentsBuilder.fromHttpUrl(s4Url).build(documentId)).exchange()
.flatMap(result -> result.toEntity(byte[].class)).block();
log.info("S4 URL : {}", s4Url);
if(response.getStatusCode().is2xxSuccessful()) {
//Getting the name of the file
HttpHeaders responseHeaders = response.getHeaders();
Optional<List<String>> list = Optional.ofNullable(responseHeaders.get("content-disposition"));
if (list.isPresent()) {
Optional<String> token = Optional.ofNullable(list.get().get(0));
if (token.isPresent()) {
fileName = token.get();
}
}
fileName = fileName.substring(18,fileName.length()-1);
byte[] arr = response.getBody();
ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ZipInputStream zis = new ZipInputStream(bais);
String path = "BOOT-INF/classes/temp";
File file1 = new File(path);
file1.mkdir();
String filePath = path + fileName;
FileOutputStream fos = new FileOutputStream(filePath);
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len;
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
bos.close();
byte[] entries = bos.toByteArray();
ZipEntry newentry = new ZipEntry(zipEntry.getName());
System.out.println(newentry.getName());
zos.putNextEntry(newentry);
zos.write(entries);
zos.closeEntry();
}
zos.close();
zis.close();
try {
if (!s3Client.doesBucketExistV2(bucketName)) {
// Because the CreateBucketRequest object doesn't specify a region, the
// bucket is created in the region specified in the client.
s3Client.createBucket(new CreateBucketRequest(bucketName));
}
} catch (AmazonServiceException e) {
// The call was transmitted successfully, but Amazon S3 couldn't process
// it and returned an error response.
e.printStackTrace();
} catch (SdkClientException e) {
// Amazon S3 couldn't be contacted for a response, or the client
// couldn't parse the response from Amazon S3.
e.printStackTrace();
}
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String folderName = formatter.format(date);
String fileKey = folderName+ "/" + fileName;
File file = new File(path + fileName);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileKey, file);
s3Client.putObject(putObjectRequest);
file.delete();
// fetching the signed url
Date expiration = new Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 30 * 60;
expiration.setTime(expTimeMillis);
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, fileKey)
.withMethod(HttpMethod.GET);
signedUrl = s3Client.generatePresignedUrl(generatePresignedUrlRequest).toString();
System.out.println(signedUrl);
return ResponseEntity.ok().body(signedUrl);
}
else {
return ResponseEntity.status(HttpStatus.valueOf(response.getStatusCodeValue())).body(response.getBody());
}
}
}
package com.ford.ierp.epayableseuservice.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.amazonaws.Protocol;
import org.apache.http.conn.ssl.SSLSocketFactory;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.emc.ecs.connector.S3ServiceInfo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@SuppressWarnings("deprecation")
@Configuration
public class AwsS3Config {
@Autowired
private S3ServiceInfo s3ServiceInfo;
@Bean("AmazonS3")
public AmazonS3 getAmazonS3(){
final ClientConfiguration httpsClientConfig = new ClientConfiguration().withProtocol(Protocol.HTTPS).withSignerOverride("S3SignerType");
httpsClientConfig.getApacheHttpClientConfig().setSslSocketFactory(SSLSocketFactory.getSystemSocketFactory());
AmazonS3 client = AmazonS3ClientBuilder.standard()
.withPathStyleAccessEnabled(true)
.withForceGlobalBucketAccessEnabled(true)
.withClientConfiguration(httpsClientConfig)
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(s3ServiceInfo.getAccessKey(), s3ServiceInfo.getSecretKey())))
.withEndpointConfiguration(new EndpointConfiguration(endpointUrlWithNamespace(s3ServiceInfo.getEndpoint(), s3ServiceInfo.getAccessKey()), null))
.build();
return client;
}
protected String endpointUrlWithNamespace(String endpoint, String accessKey) {
//extract namespace from access-key (verify format)
Matcher matcher = Pattern.compile("((.+?-){3}ns\\d\\d)-").matcher(accessKey);
if (!matcher.find()) return endpoint;
String namespace = matcher.group(1);
return endpoint.contains("://s3-object") ? endpoint.replace("://", "://" + namespace + ".") : endpoint;
}
} package com.ford.ierp.epayableseuservice.configuration; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.emc.ecs.connector.S3ServiceInfo; @Configuration public class S3LocalServiceInfoConfig { @Bean public S3ServiceInfo s3ServiceInfo( @Value("${s3.access.key}") String accessKey, @Value("${s3.secret.key}") String secretKey, @Value("${s3.endpoint}") String endpoint, @Value("${s3.bucket}") String bucket) { return new S3ServiceInfo(null, accessKey, secretKey, endpoint, bucket); } }

package com.ford.ierp.epayableseuservice.serviceimpl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import org.springframework.web.util.UriComponentsBuilder;
import com.ford.ierp.epayableseuservice.service.PdfDownloadPOCService;
@Service
public class PdfDownloadPOCServiceImpl implements PdfDownloadPOCService {
@Autowired
@Qualifier("Epayables")
WebClient webClient;
@Value("${s4.pdf.download.url}")
private String s4PdfDownloadUrl;
@Override
public ResponseEntity<StreamingResponseBody> generatePDF(String documentId) throws IOException {
String s4Url = s4PdfDownloadUrl;
ResponseEntity<StreamingResponseBody> response = null;
if (documentId.contains(",")) {
documentId = documentId.replace(",", "|");
}
@SuppressWarnings("deprecation")
ResponseEntity<byte[]> response1 = webClient.get()
.uri(UriComponentsBuilder.fromHttpUrl(s4Url).build(documentId)).exchange()
.flatMap(result -> result.toEntity(byte[].class)).block();
if(response1.getStatusCode().is2xxSuccessful()) {
response = ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=\"PDFFile.zip\"")
.body(getStreamingResponseBody(response1.getBody()));
}
else {
response = ResponseEntity.status(HttpStatus.valueOf(response1.getStatusCodeValue())).body(null);
}
return response;
}
private StreamingResponseBody getStreamingResponseBody(byte[] body) {
return out -> {
ByteArrayInputStream bais = new ByteArrayInputStream(body);
ZipInputStream zis = new ZipInputStream(bais);
ZipOutputStream zos = new ZipOutputStream(out);
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len;
while ((len = zis.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
bos.close();
byte[] entries = bos.toByteArray();
ZipEntry newentry = new ZipEntry(zipEntry.getName());
zos.putNextEntry(newentry);
zos.write(entries);
zos.closeEntry();
}
zos.close();
zis.close();
};
}
}

Comments