Skip to content

Commit 74bc078

Browse files
Add the download functionality to the Spring BOOT Photo example (#1933)
* Create Readme.md * Create CreateCluster.java * Add files via upload * Update Readme.md * Create EcsTest.java * Create config.properties * Update Readme.md * Add files via upload * Add files via upload * Add files via upload * Update ArchiveDownload.java * Update DescribeInstanceTags.java * Update Readme.md * Update Readme.md * Update Readme.md * Update Readme.md * Update ArchiveDownload.java * Update Readme.md * Add files via upload * Update Readme.md * Update PhotoController.java * Update AnalyzePhotos.java * Update BucketItem.java * Update PhotoApplication.java * Update S3Service.java * Update SendMessages.java * Update WorkItem.java * Update WriteExcel.java * Update Readme.md * Update process.html * Update message.js * Update Readme.md * Update Readme.md * Update S3Service.java * Update PhotoController.java * Update Readme.md * Update PhotoController.java * Update Readme.md * Update EcsTest.java * Delete EcsTest.java Co-authored-by: Irene Smith <[email protected]>
1 parent 0545373 commit 74bc078

File tree

12 files changed

+216
-87
lines changed

12 files changed

+216
-87
lines changed

javav2/usecases/creating_photo_analyzer_app/Readme.md

Lines changed: 105 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Creating an example AWS photo analyzer application using the AWS SDK for Java
22

3+
## Purpose
34
You can create an AWS application that analyzes nature images located in an Amazon Simple Storage Service (Amazon S3) bucket by using the Amazon Rekognition service.
45

56
The application can analyze many images and generate a report that breaks down each image into a series of labels.
@@ -26,10 +27,6 @@ This application uses the following AWS services:
2627
* Amazon SES
2728
* AWS Elastic Beanstalk
2829

29-
**Cost to complete:** The AWS services included in this document are included in the [AWS Free Tier](https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc).
30-
31-
**Note:** Be sure to terminate all of the resources you create while going through this tutorial to ensure that you’re no longer charged for them.
32-
3330
#### Topics
3431

3532
+ Prerequisites
@@ -50,7 +47,17 @@ To complete the tutorial, you need the following:
5047
+ A Java IDE (this tutorial uses the IntelliJ IDE)
5148
+ Java JDK 1.8
5249
+ Maven 3.6 or later
53-
+ An Amazon S3 bucket named **photos[somevalue]**. Be sure to use this bucket name in your Amazon S3 Java code. For information, see [Creating a bucket](https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html).
50+
51+
### Important
52+
53+
+ The AWS services included in this document are included in the [AWS Free Tier](https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc).
54+
+ This code has not been tested in all AWS Regions. Some AWS services are available only in specific regions. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
55+
+ Running this code might result in charges to your AWS account.
56+
+ Be sure to terminate all of the resources you create while going through this tutorial to ensure that you’re not charged.
57+
58+
### Creating the resources
59+
60+
Create an Amazon S3 bucket named **photos[somevalue]**. Be sure to use this bucket name in your Amazon S3 Java code. For information, see [Creating a bucket](https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html).
5461

5562
## Understand the AWS Photo Analyzer application
5663

@@ -62,6 +69,10 @@ To generate a report, enter an email address and choose **Analyze Photos**.
6269

6370
![AWS Photo Analyzer](images/photo2.png)
6471

72+
You can also download a given image from the Amazon S3 bucket by using this application. Simply specify the image name and choose the **Download Photo** button. The image is downloaded to your browser, as shown in this illustration.
73+
74+
![AWS Photo Analyzer](images/download.png)
75+
6576
## Create an IntelliJ project named SpringPhotoAnalyzer
6677

6778
1. In the IntelliJ IDE, choose **File**, **New**, **Project**.
@@ -359,6 +370,8 @@ The following Java code represents the **PhotoApplication** class.
359370

360371
The following Java code represents the **PhotoController** class that handles HTTP requests. For example, when a new image is posted (uploaded to an S3 bucket), the **singleFileUpload** method handles the request.
361372

373+
**Note**: Be sure that you change the **bucketName** variable to your Amazon S3 bucket name.
374+
362375
package com.example.photo;
363376

364377
import org.springframework.beans.factory.annotation.Autowired;
@@ -369,13 +382,17 @@ The following Java code represents the **PhotoController** class that handles HT
369382
import org.springframework.web.servlet.ModelAndView;
370383
import org.springframework.web.multipart.MultipartFile;
371384
import org.springframework.web.servlet.view.RedirectView;
385+
import java.io.ByteArrayInputStream;
372386
import java.io.IOException;
373387
import java.io.InputStream;
374388
import java.util.*;
375389

376390
@Controller
377391
public class PhotoController {
378392

393+
// Change to your Bucket Name!
394+
private String bucketName = "<YOUR BUCKET>";
395+
379396
@Autowired
380397
S3Service s3Client;
381398

@@ -407,69 +424,92 @@ The following Java code represents the **PhotoController** class that handles HT
407424
@ResponseBody
408425
String getImages(HttpServletRequest request, HttpServletResponse response) {
409426

410-
return s3Client.ListAllObjects("scottphoto");
427+
return s3Client.ListAllObjects(bucketName);
411428
}
412429

413-
// Generate a report that analyzes photos in a given bucket
430+
// Generates a report that analyzes photos in a given bucket.
414431
@RequestMapping(value = "/report", method = RequestMethod.POST)
415432
@ResponseBody
416433
String report(HttpServletRequest request, HttpServletResponse response) {
417434

418435
String email = request.getParameter("email");
419436

420-
// Get a list of key names in the given bucket
421-
List myKeys = s3Client.ListBucketObjects("scottphoto");
437+
// Get a list of key names in the given bucket.
438+
List myKeys = s3Client.ListBucketObjects(bucketName);
422439

423-
// Create a list to store the data
424-
List myList = new ArrayList<List>();
440+
// Create a List to store the data.
441+
List<List> myList = new ArrayList<List>();
425442

426-
// Loop through each element in the List
443+
// loop through each element in the List.
427444
int len = myKeys.size();
428445
for (int z=0 ; z < len; z++) {
429446

430447
String key = (String) myKeys.get(z);
431-
byte[] keyData = s3Client.getObjectBytes ("scottphoto", key);
432-
//myMap.put(key, keyData);
448+
byte[] keyData = s3Client.getObjectBytes (bucketName, key);
433449

434-
// Analyze the photo
450+
//Analyze the photo.
435451
ArrayList item = photos.DetectLabels(keyData, key);
436452
myList.add(item);
437453
}
438454

439-
// Now we have a list of WorkItems that have all of the analytical data describing the photos in the S3 bucket
455+
// Now we have a list of WorkItems that have all of the analytical data describing the photos in the S3 bucket.
440456
InputStream excelData = excel.exportExcel(myList);
441457

442458
try {
443-
// Email the report
459+
// Email the report.
444460
sendMessage.sendReport(excelData, email);
445461

446462
} catch (Exception e) {
447463

448464
e.printStackTrace();
449465
}
450-
return "The photos have been analyzed and the report is sent.";
466+
return "The photos have been analyzed and the report is sent";
451467
}
452468

453-
// Upload an image to send to an S3 bucket
469+
// Upload a video to analyze.
454470
@RequestMapping(value = "/upload", method = RequestMethod.POST)
455471
@ResponseBody
456472
public ModelAndView singleFileUpload(@RequestParam("file") MultipartFile file) {
457473

458474
try {
459475

460-
// Now you can add this to an S3 bucket
461476
byte[] bytes = file.getBytes();
462477
String name = file.getOriginalFilename() ;
463478

464-
// Put the file into the bucket
465-
s3Client.putObject(bytes, "scottphoto", name);
479+
// Put the file into the bucket.
480+
s3Client.putObject(bytes, bucketName, name);
466481

467482
} catch (IOException e) {
468483
e.printStackTrace();
469484
}
470485
return new ModelAndView(new RedirectView("photo"));
486+
}
487+
488+
489+
// This controller method downloads the given image from the Amazon S3 bucket.
490+
@RequestMapping(value = "/downloadphoto", method = RequestMethod.GET)
491+
void buildDynamicReportDownload(HttpServletRequest request, HttpServletResponse response) {
492+
try {
493+
494+
// Get the form id from the submitted form.
495+
String photoKey = request.getParameter("photoKey");
496+
byte[] photoBytes = s3Client.getObjectBytes(bucketName, photoKey) ;
497+
InputStream is = new ByteArrayInputStream(photoBytes);
498+
499+
// Define the required information here.
500+
response.setContentType("image/png");
501+
response.setHeader("Content-disposition", "attachment; filename="+photoKey);
502+
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
503+
response.flushBuffer();
504+
505+
} catch (Exception e) {
506+
e.printStackTrace();
471507
}
472-
}
508+
}
509+
}
510+
511+
512+
473513

474514
### S3Service class
475515

@@ -505,30 +545,30 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
505545

506546
S3Client s3 ;
507547

548+
// Create the S3Client object.
508549
private S3Client getClient() {
509-
// Create the S3Client object
550+
510551
Region region = Region.US_WEST_2;
511552
S3Client s3 = S3Client.builder()
512553
.credentialsProvider(EnvironmentVariableCredentialsProvider.create())
513554
.region(region)
514555
.build();
515556

516557
return s3;
517-
}
558+
}
518559

560+
// Get the byte[] from this AWS S3 object.
519561
public byte[] getObjectBytes (String bucketName, String keyName) {
520562

521563
s3 = getClient();
522564

523565
try {
524-
// Create a GetObjectRequest instance
525566
GetObjectRequest objectRequest = GetObjectRequest
526567
.builder()
527568
.key(keyName)
528569
.bucket(bucketName)
529570
.build();
530-
531-
// Get the byte[] from this S3 object
571+
532572
ResponseBytes<GetObjectResponse> objectBytes = s3.getObjectAsBytes(objectRequest);
533573
byte[] data = objectBytes.asByteArray();
534574
return data;
@@ -538,9 +578,9 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
538578
System.exit(1);
539579
}
540580
return null;
541-
}
581+
}
542582

543-
// Return the names of all images and data within an XML document
583+
// Returns the names of all images and data within an XML document.
544584
public String ListAllObjects(String bucketName) {
545585

546586
s3 = getClient();
@@ -579,9 +619,9 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
579619
System.exit(1);
580620
}
581621
return null ;
582-
}
622+
}
583623

584-
// Return the names of all images in the given bucket
624+
// Returns the names of all images in the given bucket.
585625
public List ListBucketObjects(String bucketName) {
586626

587627
s3 = getClient();
@@ -604,7 +644,7 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
604644
keys.add(keyName);
605645
}
606646

607-
return keys;
647+
return keys;
608648

609649
} catch (S3Exception e) {
610650
System.err.println(e.awsErrorDetails().errorMessage());
@@ -614,13 +654,12 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
614654
}
615655

616656

617-
// Place an image into an S3 bucket
657+
// Places an image into a S3 bucket.
618658
public String putObject(byte[] data, String bucketName, String objectKey) {
619659

620660
s3 = getClient();
621661

622662
try {
623-
// Put a file into the bucket
624663
PutObjectResponse response = s3.putObject(PutObjectRequest.builder()
625664
.bucket(bucketName)
626665
.key(objectKey)
@@ -634,59 +673,59 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
634673
System.exit(1);
635674
}
636675
return "";
637-
}
676+
}
638677

639-
// Convert bucket item data into XML to pass back to the view
678+
// Convert items into XML to pass back to the view.
640679
private Document toXml(List<BucketItem> itemList) {
641680

642681
try {
643682
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
644683
DocumentBuilder builder = factory.newDocumentBuilder();
645684
Document doc = builder.newDocument();
646685

647-
// Start building the XML
686+
// Start building the XML.
648687
Element root = doc.createElement( "Items" );
649688
doc.appendChild( root );
650689

651-
// Get the elements from the collection
690+
// Get the elements from the collection.
652691
int custCount = itemList.size();
653692

654-
// Iterate through the collection
693+
// Iterate through the collection.
655694
for ( int index=0; index < custCount; index++) {
656695

657-
// Get the WorkItem object from the collection
696+
// Get the WorkItem object from the collection.
658697
BucketItem myItem = itemList.get(index);
659698

660699
Element item = doc.createElement( "Item" );
661700
root.appendChild( item );
662701

663-
// Set Key
702+
// Set Key.
664703
Element id = doc.createElement( "Key" );
665704
id.appendChild( doc.createTextNode(myItem.getKey()) );
666705
item.appendChild( id );
667706

668-
// Set Owner
707+
// Set Owner.
669708
Element name = doc.createElement( "Owner" );
670709
name.appendChild( doc.createTextNode(myItem.getOwner() ) );
671710
item.appendChild( name );
672711

673-
// Set Date
712+
// Set Date.
674713
Element date = doc.createElement( "Date" );
675714
date.appendChild( doc.createTextNode(myItem.getDate() ) );
676715
item.appendChild( date );
677716

678-
// Set Size
717+
// Set Size.
679718
Element desc = doc.createElement( "Size" );
680719
desc.appendChild( doc.createTextNode(myItem.getSize() ) );
681720
item.appendChild( desc );
682-
}
721+
}
683722

684723
return doc;
685724
} catch(ParserConfigurationException e) {
686725
e.printStackTrace();
687726
}
688727
return null;
689-
}
728+
}
690729

691730
private String convertToString(Document xml) {
692731
try {
@@ -700,8 +739,9 @@ The following class uses the Amazon S3 API to perform S3 operations. For example
700739
ex.printStackTrace();
701740
}
702741
return null;
703-
}
704-
}
742+
}
743+
}
744+
705745

706746
### SendMessage class
707747

@@ -1160,6 +1200,14 @@ The following HTML represents the **process.html** file.
11601200
<p>Choose the button to obtain a report.</p>
11611201
<button onclick="ProcessImages()">Analyze Photos</button>
11621202
</div>
1203+
<div>
1204+
<h3>Download a photo to your browser</h3>
1205+
<p>Specify the photo to download from an Amazon S3 bucket</p>
1206+
<label for="photo">Photo Name:"</label><br>
1207+
<input type="text" id="photo" name="photo" value=""><br>
1208+
<p>Click the following button to download a photo</p>
1209+
<button onclick="DownloadImage()">Download Photo</button>
1210+
</div>
11631211
</div>
11641212
</body>
11651213
</html>
@@ -1358,6 +1406,14 @@ The following JavaScript represents the **message.js** file. The **ProcessImages
13581406
var res = event.target.responseText;
13591407
alert(res) ;
13601408
}
1409+
1410+
function DownloadImage(){
1411+
1412+
//Post the values to the controller
1413+
var photo = $('#photo').val();
1414+
window.location="../downloadphoto?photoKey=" + photo ;
1415+
}
1416+
13611417

13621418
**Note:** There are other CSS files located in the GitHub repository that you must add to your project. Ensure all of the files under the **resources** folder are included in your project.
13631419

Loading

javav2/usecases/creating_photo_analyzer_app/src/main/java/com/example/photo/AnalyzePhotos.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
16
package com.example.photo;
27

38
import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;

0 commit comments

Comments
 (0)