diff --git a/assets/config/opensrp.properties b/assets/config/opensrp.properties index aebad7f8c1..8a43132706 100644 --- a/assets/config/opensrp.properties +++ b/assets/config/opensrp.properties @@ -5,9 +5,7 @@ form.poll.time.interval=2 mcts.phone.number=8762963816 js.directory.name=/ziggy form.directory.name=/form -multimedia.directory.name=/opt/multimedia form.download.files=form.xml, model.xml, form_definition.json -multimedia.directory.name=../multimedia/opensrp qrcodes.directory.name=/home/opensrp/qr-codes/ schedule.config.path=/schedules/schedule-config.xls @@ -59,7 +57,6 @@ jdbc.url-wo-db=jdbc:mysql://localhost:3306 # Hibernate properties for Reporting DB hibernate.dialect=org.hibernate.dialect.MySQLDialect -hibernate.show_sql=false # hibernate.hbm2ddl.auto=update hibernate.show_sql=true hibernate.format_sql=false @@ -88,3 +85,16 @@ file.maxUploadSize=20971520 #opnenSRP Site url opensrp.site.url="" + +#multimedia directory location - accepted values (s3 or local) +multimedia.directory.location = s3 + +#if local is preferred this path will be used to store images +multimedia.directory.name= "" + +# S3 configuration +aws.access.key.id = "" +aws.secret.access.key = "" +aws.region = "" +aws.bucket = "" +aws.key.folder = "" diff --git a/opensrp-core/pom.xml b/opensrp-core/pom.xml index 40ff3f1015..5c2557a226 100644 --- a/opensrp-core/pom.xml +++ b/opensrp-core/pom.xml @@ -25,7 +25,7 @@ ../assets/schedules schedules - + ../build true @@ -46,6 +46,12 @@ + + + com.amazonaws + aws-java-sdk + 1.11.244 + motech-platform-server-api org.motechproject @@ -60,7 +66,7 @@ com.fasterxml.jackson.core jackson-databind - 2.2.2 + 2.6.0 @@ -207,7 +213,7 @@ org.springframework.data spring-data-jpa 1.1.0.RELEASE - + nl.jqno.equalsverifier equalsverifier @@ -218,7 +224,7 @@ com.openpojo openpojo 0.8.6 - + org.hibernate @@ -239,7 +245,7 @@ test runtime - - + + diff --git a/opensrp-core/src/main/java/org/opensrp/service/MultimediaService.java b/opensrp-core/src/main/java/org/opensrp/service/MultimediaService.java index 767c99e637..97f9a457ff 100644 --- a/opensrp-core/src/main/java/org/opensrp/service/MultimediaService.java +++ b/opensrp-core/src/main/java/org/opensrp/service/MultimediaService.java @@ -1,8 +1,16 @@ package org.opensrp.service; -import java.io.File; -import java.util.List; - +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; +import org.json.JSONException; import org.opensrp.domain.Client; import org.opensrp.domain.Multimedia; import org.opensrp.dto.form.MultimediaDTO; @@ -14,109 +22,110 @@ import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.List; + @Service public class MultimediaService { - + private static Logger logger = LoggerFactory.getLogger(MultimediaService.class.toString()); - + public static final String IMAGES_DIR = "patient_images"; - + private static final String VIDEOS_DIR = "videos"; - + private final MultimediaRepository multimediaRepository; - + private final ClientService clientService; - + private String multimediaDirPath; - + @Value("#{opensrp['multimedia.directory.name']}") - String baseMultimediaDirPath; - + private String baseMultimediaDirPath; + + @Value("#{opensrp['aws.access.key.id']}") + private String awsAccessKeyId; + + @Value("#{opensrp['aws.secret.access.key']}") + private String awsSecretAccessKey; + + @Value("#{opensrp['aws.region']}") + private String awsRegion; + + @Value("#{opensrp['aws.bucket']}") + private String awsBucket; + + @Value("#{opensrp['aws.key.folder']}") + private String mediaKeyFolder; + + @Value("#{opensrp['multimedia.directory.location']}") + private String multimediaDirectoryLocation; + + private String successResponse = "success"; + + private String failedResponse = "fail"; + + private String imageAttribute = "Patient Image"; + @Autowired public MultimediaService(MultimediaRepository multimediaRepository, ClientService clientService) { this.multimediaRepository = multimediaRepository; this.clientService = clientService; } - + public String saveMultimediaFile(MultimediaDTO multimediaDTO, MultipartFile file) { + String fileExtension = makeFileExtension(multimediaDTO); + + if (multimediaDirectoryLocation.equalsIgnoreCase("s3")) { + File imageToSave = new File(multimediaDTO.getCaseId() + fileExtension); + try { + file.transferTo(imageToSave); + uploadImageToS3(imageToSave, awsAccessKeyId, awsSecretAccessKey, awsRegion, awsBucket, mediaKeyFolder); + updateClientWithImage(multimediaDTO, fileExtension); + return successResponse; + } catch (IOException e) { + e.printStackTrace(); + return failedResponse; + } + } + if (uploadFile(multimediaDTO, file)) { try { logger.info("Image path : " + multimediaDirPath); - Multimedia multimediaFile = new Multimedia().withCaseId(multimediaDTO.getCaseId()) - .withProviderId(multimediaDTO.getProviderId()).withContentType(multimediaDTO.getContentType()) - .withFilePath(multimediaDTO.getFilePath()).withFileCategory(multimediaDTO.getFileCategory()); - + .withProviderId(multimediaDTO.getProviderId()).withContentType(multimediaDTO.getContentType()) + .withFilePath(multimediaDTO.getFilePath()).withFileCategory(multimediaDTO.getFileCategory()); multimediaRepository.add(multimediaFile); - Client client = clientService.getByBaseEntityId(multimediaDTO.getCaseId()); - if (client !=null) { - if(client.getAttribute("Patient Image") != null) { - client.removeAttribute("Patient Image"); - } - client.addAttribute("Patient Image", multimediaDTO.getCaseId() + ".jpg"); - client.setServerVersion(null); - clientService.updateClient(client); - } - return "success"; + updateClientWithImage(multimediaDTO, fileExtension); + return successResponse; } catch (Exception e) { e.getMessage(); + return failedResponse; } } - - return "fail"; + return failedResponse; } - + public boolean uploadFile(MultimediaDTO multimediaDTO, MultipartFile multimediaFile) { - - // String baseMultimediaDirPath = System.getProperty("user.home"); - + if (!multimediaFile.isEmpty()) { try { - + multimediaDirPath = baseMultimediaDirPath + File.separator; - String fileExt = ".jpg"; - switch (multimediaDTO.getContentType()) { - - case "application/octet-stream": - multimediaDirPath += VIDEOS_DIR; - fileExt = ".mp4"; - break; - - case "image/jpeg": - multimediaDirPath += IMAGES_DIR; - fileExt = ".jpg"; - break; - - case "image/gif": - multimediaDirPath += IMAGES_DIR; - fileExt = ".gif"; - break; - - case "image/png": - multimediaDirPath += IMAGES_DIR; - fileExt = ".png"; - break; - - } new File(multimediaDirPath).mkdir(); - String fileName = multimediaDirPath + File.separator + multimediaDTO.getCaseId() + fileExt; + String fileName = + multimediaDirPath + File.separator + multimediaDTO.getCaseId() + makeFileExtension(multimediaDTO); multimediaDTO.withFilePath(fileName); File multimediaDir = new File(fileName); - multimediaFile.transferTo(multimediaDir); - - /* - byte[] bytes = multimediaFile.getBytes(); - - BufferedOutputStream stream = new BufferedOutputStream( - new FileOutputStream(multimediaDirPath)); - stream.write(bytes); - stream.close();*/ - + return true; - } catch (Exception e) { logger.error("", e); @@ -126,19 +135,83 @@ public boolean uploadFile(MultimediaDTO multimediaDTO, MultipartFile multimediaF return false; } } - - private void makeMultimediaDir(String dirPath) { - File file = new File(dirPath); - if (!file.exists()) - file.mkdirs(); - - } - + public List getMultimediaFiles(String providerId) { return multimediaRepository.all(providerId); } - + public Multimedia findByCaseId(String entityId) { return multimediaRepository.findByCaseId(entityId); } + + public String uploadImageToS3(File imageFile, String awsAccessKeyId, String awsSecretAccessKey, String awsRegion, + String awsBucket, String awsKeyFolder) { + + AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials( + new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKeyId, awsSecretAccessKey))) + .withRegion(awsRegion).build(); + InputStream inputStream; + try { + byte[] md5 = DigestUtils.md5(new FileInputStream(imageFile)); + inputStream = new FileInputStream(imageFile); + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(imageFile.length()); + metadata.setContentMD5(new String(Base64.encodeBase64(md5))); + PutObjectRequest request = new PutObjectRequest(awsBucket, awsKeyFolder + imageFile.getName(), inputStream, + metadata); + s3Client.putObject(request); + return successResponse; + } + catch (AmazonServiceException e) { + logger.error("", e); + return failedResponse; + } + catch (SdkClientException e) { + logger.error("", e); + return failedResponse; + } + catch (FileNotFoundException e) { + logger.error("", e); + return failedResponse; + } + catch (IOException e) { + logger.error("", e); + return failedResponse; + } + } + + public String makeFileExtension(MultimediaDTO multimediaDTO) { + switch (multimediaDTO.getContentType()) { + case "application/octet-stream": + multimediaDirPath += VIDEOS_DIR; + return ".mp4"; + + case "image/gif": + multimediaDirPath += IMAGES_DIR; + return ".gif"; + + case "image/png": + multimediaDirPath += IMAGES_DIR; + return ".png"; + default: + return ".jpg"; + } + } + + public void updateClientWithImage(MultimediaDTO multimediaDTO, String fileExtension) { + Client client = clientService.getByBaseEntityId(multimediaDTO.getCaseId()); + if (client != null) { + try { + if (client.getAttribute(imageAttribute) != null) { + client.removeAttribute(imageAttribute); + } + client.addAttribute(imageAttribute, multimediaDTO.getCaseId() + fileExtension); + client.setServerVersion(null); + clientService.updateClient(client); + } + catch (JSONException e) { + e.printStackTrace(); + } + } + } } diff --git a/opensrp-core/src/test/java/org/opensrp/MultimediaServiceTest.java b/opensrp-core/src/test/java/org/opensrp/MultimediaServiceTest.java index f06480f989..995bf5271d 100644 --- a/opensrp-core/src/test/java/org/opensrp/MultimediaServiceTest.java +++ b/opensrp-core/src/test/java/org/opensrp/MultimediaServiceTest.java @@ -1,19 +1,24 @@ package org.opensrp; -import static org.mockito.MockitoAnnotations.initMocks; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.List; - +import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.ClientConfiguration; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.GetObjectRequest; +import com.amazonaws.services.s3.model.S3Object; +import com.amazonaws.services.s3.model.S3ObjectInputStream; +import com.amazonaws.util.IOUtils; +import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.opensrp.domain.Multimedia; import org.opensrp.dto.form.MultimediaDTO; import org.opensrp.repository.MultimediaRepository; @@ -26,38 +31,78 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.FileNotFoundException; + +import java.net.URL; +import java.util.List; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:test-applicationContext-opensrp.xml") public class MultimediaServiceTest { - + + @Value("#{opensrp['aws.access.key.id']}") + private String awsAccessKeyId; + + @Value("#{opensrp['aws.secret.access.key']}") + private String awsSecretAccessKey; + + @Value("#{opensrp['aws.region']}") + private String awsRegion; + + @Value("#{opensrp['aws.bucket']}") + private String awsBucket; + + @Value("#{opensrp['aws.key.folder']}") + private String mediaKeyFolder; + @Mock private MultimediaService multimediaService; - + @Autowired private MultimediaRepository multimediaRepository; - + @Autowired private ClientService clientService; - + @Autowired @Value("#{opensrp['multimedia.directory.name']}") private String multimediaDirPath; - + + private static final int MAX_ERROR_RETRY = 5; + + private static final int MAX_CONNECTIONS = 5000; + + private static final int MAX_CONNECTION_TIME_OUT = 5000; + + private static final int SOCKET_TIME_OUT = 5000; + + public static final int BUFFER_SIZE = 1024; + + private URL url; + + private File expectedImage; + @Before public void setUp() throws Exception { - initMocks(this); + MockitoAnnotations.initMocks(this); + url = new URL("https://www.dropbox.com/s/cwazpyy2mipj865/gimage.png"); + expectedImage = new File("s3image.jpg"); multimediaService = new MultimediaService(multimediaRepository, clientService); } - + @Ignore @Test public void shouldSaveMultimediaFile() throws FileNotFoundException { MultimediaDTO multimedia = new MultimediaDTO("1234567891", "opensrp", "image/jpeg", "", "nid"); String baseDirPath = System.getProperty("user.home"); FileInputStream fis = new FileInputStream(baseDirPath + File.separator + ".OpenSRP/multimedia/image.jpeg"); - + MultipartFile multipartFile = null; - + try { multipartFile = new MockMultipartFile("file", fis); } @@ -65,43 +110,94 @@ public void shouldSaveMultimediaFile() throws FileNotFoundException { // TODO Auto-generated catch block e.printStackTrace(); } - + String status = multimediaService.saveMultimediaFile(multimedia, multipartFile); - + Assert.assertEquals("success", status); - + } - + @Ignore @Test public void shouldGetMultimediaFiles() throws FileNotFoundException { MultimediaDTO multimediaDTO = new MultimediaDTO("1234567890", "opensrp", "image/jpeg", "", "profile"); - + Multimedia expectedMultimedia = new Multimedia().withCaseId(multimediaDTO.getCaseId()) - .withProviderId(multimediaDTO.getProviderId()).withContentType(multimediaDTO.getContentType()) - .withFilePath(multimediaDTO.getFilePath()).withFileCategory(multimediaDTO.getFileCategory()); - + .withProviderId(multimediaDTO.getProviderId()).withContentType(multimediaDTO.getContentType()) + .withFilePath(multimediaDTO.getFilePath()).withFileCategory(multimediaDTO.getFileCategory()); + String baseDirPath = System.getProperty("user.home"); FileInputStream fis = new FileInputStream(baseDirPath + File.separator + ".OpenSRP/multimedia/image.jpeg"); MultipartFile multipartFile = null; - + try { multipartFile = new MockMultipartFile("file", fis); } catch (IOException e) { e.printStackTrace(); } - + boolean status = multimediaService.uploadFile(multimediaDTO, multipartFile); - + if (status) multimediaRepository.add(expectedMultimedia); - + List multimediaFiles = multimediaService.getMultimediaFiles("opensrp"); - + for (Multimedia actualMultimedia : multimediaFiles) { if (actualMultimedia.getCaseId().equals(multimediaDTO.getCaseId())) Assert.assertEquals(expectedMultimedia.getFilePath(), actualMultimedia.getFilePath()); } } + + @Ignore + @Test + public void shouldSaveImageTos3() throws Exception { + FileUtils.copyURLToFile(url, expectedImage); + Assert.assertEquals("success", multimediaService + .uploadImageToS3(expectedImage, awsAccessKeyId, awsSecretAccessKey, awsRegion, awsBucket, mediaKeyFolder)); + + } + + @Ignore + @Test + public void shouldDownloadImageFroms3() throws Exception { + FileUtils.copyURLToFile(url, expectedImage); + ClientConfiguration clientConfiguration = new ClientConfiguration().withMaxErrorRetry(MAX_ERROR_RETRY) + .withMaxConnections(MAX_CONNECTIONS).withConnectionTimeout(MAX_CONNECTION_TIME_OUT) + .withSocketTimeout(SOCKET_TIME_OUT); + + AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials( + new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKeyId, awsSecretAccessKey))) + .withClientConfiguration(clientConfiguration).withRegion(awsRegion).build(); + + OutputStream fetchedOutputStream = null; + OutputStream expectedOutputStream = null; + try { + S3Object object = s3Client.getObject(new GetObjectRequest(awsBucket, mediaKeyFolder + "gimage.png")); + S3ObjectInputStream objectContent = object.getObjectContent(); + IOUtils.copy(objectContent, fetchedOutputStream); + + byte[] buffer = new byte[BUFFER_SIZE]; + int count; + FileInputStream fileInputStream = new FileInputStream(expectedImage); + while ((count = fileInputStream.read(buffer)) >= 0) { + expectedOutputStream.write(buffer, 0, count); + } + Assert.assertEquals(expectedOutputStream, fetchedOutputStream); + expectedOutputStream.flush(); + fetchedOutputStream.flush(); + object.close(); + objectContent.close(); + } + catch (AmazonServiceException aws) { + aws.printStackTrace(); + } + catch (AmazonClientException aws) { + aws.printStackTrace(); + } + catch (IOException io) { + io.printStackTrace(); + } + } } diff --git a/opensrp-web/src/main/java/org/opensrp/web/controller/MultimediaController.java b/opensrp-web/src/main/java/org/opensrp/web/controller/MultimediaController.java index d2b5d1fb61..34e89b4259 100644 --- a/opensrp-web/src/main/java/org/opensrp/web/controller/MultimediaController.java +++ b/opensrp-web/src/main/java/org/opensrp/web/controller/MultimediaController.java @@ -1,18 +1,16 @@ package org.opensrp.web.controller; -import static org.springframework.web.bind.annotation.RequestMethod.POST; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URLConnection; -import java.nio.charset.Charset; - -import javax.servlet.http.HttpServletResponse; - +import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.ClientConfiguration; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.GetObjectRequest; +import com.amazonaws.services.s3.model.S3Object; +import com.amazonaws.services.s3.model.S3ObjectInputStream; +import com.google.gson.Gson; import org.opensrp.domain.Multimedia; import org.opensrp.dto.form.MultimediaDTO; import org.opensrp.service.MultimediaService; @@ -35,30 +33,68 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; -import com.google.gson.Gson; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.BufferedInputStream; +import java.net.URLConnection; +import java.nio.charset.Charset; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; @Controller @RequestMapping("/multimedia") public class MultimediaController { - + private static Logger logger = LoggerFactory.getLogger(MultimediaController.class.toString()); - + + public static final int MAX_ERROR_RETRY = 5; + + public static final int MAX_CONNECTIONS = 5000; + + public static final int MAX_CONNECTION_TIME_OUT = 5000; + + public static final int SOCKET_TIME_OUT = 5000; + @Value("#{opensrp['multimedia.directory.name']}") - String multiMediaDir; - + private String multiMediaDir; + + @Value("#{opensrp['aws.access.key.id']}") + private String awsAccessKeyId; + + @Value("#{opensrp['aws.secret.access.key']}") + private String awsSecretAccessKey; + + @Value("#{opensrp['aws.region']}") + private String awsRegion; + + @Value("#{opensrp['aws.bucket']}") + private String awsBucket; + + @Value("#{opensrp['aws.key.folder']}") + private String mediaKeyFolder; + + @Value("#{opensrp['multimedia.directory.location']}") + private String multimediaDirectoryLocation; + @Autowired @Qualifier("drishtiAuthenticationProvider") DrishtiAuthenticationProvider provider; - + + private String fileExtension = ".jpg"; + @Autowired MultimediaService multimediaService; - + /** * Download a file from the multimedia directory. The method also assumes two file types mp4 and * images whereby all images are stored in the images folder and videos in mp4 in the multimedia * directory This method is set to bypass spring security config but authenticate through the * username/password passed at the headers - * + * * @param response * @param fileName * @param userName @@ -68,16 +104,15 @@ public class MultimediaController { @RequestMapping(value = "/download/{fileName:.+}", method = RequestMethod.GET) public void downloadFile(HttpServletResponse response, @PathVariable("fileName") String fileName, @RequestHeader(value = "username") String userName, - @RequestHeader(value = "password") String password) - throws Exception { - + @RequestHeader(value = "password") String password) throws Exception { + try { if (authenticate(userName, password).isAuthenticated()) { File file = new File(multiMediaDir + File.separator + "images" + File.separator + fileName); if (fileName.endsWith("mp4")) { file = new File(multiMediaDir + File.separator + "videos" + File.separator + fileName); } - + downloadFile(file, response); } } @@ -85,11 +120,11 @@ public void downloadFile(HttpServletResponse response, @PathVariable("fileName") logger.error("", e); } } - + /** * This method downloads a file from the server given the client id. A search is made to the * multimedia repo to see if any file exists mapped to the user whereby the filepath is recorded - * + * * @param response * @param baseEntityId * @param userName @@ -99,95 +134,141 @@ public void downloadFile(HttpServletResponse response, @PathVariable("fileName") @RequestMapping(value = "/profileimage/{baseEntityId}", method = RequestMethod.GET) public void downloadFileByClientId(HttpServletResponse response, @PathVariable("baseEntityId") String baseEntityId, @RequestHeader(value = "username") String userName, - @RequestHeader(value = "password") String password) - throws Exception { - + @RequestHeader(value = "password") String password) throws Exception { try { - if (authenticate(userName, password).isAuthenticated()) { - - Multimedia multiMedia = multimediaService.findByCaseId(baseEntityId); - if (multiMedia == null || multiMedia.getFilePath() == null) { - //see if the file exists in the disk with the assumption that it's .jpg otherwise return error msg - File file = new File(multiMediaDir + File.separator + MultimediaService.IMAGES_DIR + File.separator - + baseEntityId + ".jpg"); - if (file.exists()) { - downloadFile(file, response); - } else { - String errorMessage = "Sorry. The file you are looking for does not exist"; - logger.info(errorMessage); - OutputStream outputStream = response.getOutputStream(); - outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8"))); - outputStream.close(); - return; + if (multimediaDirectoryLocation.equalsIgnoreCase("s3")) { + downloadFileFromS3(new File(baseEntityId + fileExtension), awsAccessKeyId, awsSecretAccessKey, awsRegion, + awsBucket, mediaKeyFolder, response); + } else { + if (authenticate(userName, password).isAuthenticated()) { + Multimedia multiMedia = multimediaService.findByCaseId(baseEntityId); + if (multiMedia == null || multiMedia.getFilePath() == null) { + //see if the file exists in the disk with the assumption that it's .jpg otherwise return error msg + File file = new File( + multiMediaDir + File.separator + MultimediaService.IMAGES_DIR + File.separator + baseEntityId + + fileExtension); + if (file.exists()) { + downloadFile(file, response); + } else { + setErrorMessage(response); + return; + } } + String filePath = multiMedia.getFilePath(); + + File file = new File(filePath); + downloadFile(file, response); } - String filePath = multiMedia.getFilePath(); - - File file = new File(filePath); - downloadFile(file, response); } } catch (Exception e) { logger.error("", e); } - + } - + @RequestMapping(headers = { "Accept=multipart/form-data" }, method = POST, value = "/upload") public ResponseEntity uploadFiles(@RequestParam("anm-id") String providerId, @RequestParam("entity-id") String entityId, @RequestParam("file-category") String fileCategory, @RequestParam("file") MultipartFile file) { - + String contentType = file.getContentType(); - + MultimediaDTO multimediaDTO = new MultimediaDTO(entityId, providerId, contentType, null, fileCategory); - + String status = multimediaService.saveMultimediaFile(multimediaDTO, file); - + return new ResponseEntity<>(new Gson().toJson(status), HttpStatus.OK); } - + private Authentication authenticate(String userName, String password) { Authentication auth = new UsernamePasswordAuthenticationToken(userName, password); auth = provider.authenticate(auth); return auth; } - + private void downloadFile(File file, HttpServletResponse response) throws Exception { - + if (!file.exists()) { - String errorMessage = "Sorry. The file you are looking for does not exist"; - logger.info(errorMessage); - OutputStream outputStream = response.getOutputStream(); - outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8"))); - outputStream.close(); + setErrorMessage(response); return; } - + String mimeType = URLConnection.guessContentTypeFromName(file.getName()); if (mimeType == null) { logger.info("mimetype is not detectable, will take default"); mimeType = "application/octet-stream"; } - + logger.info("mimetype : " + mimeType); - + response.setContentType(mimeType); - - /* "Content-Disposition : inline" will show viewable types [like images/text/pdf/anything viewable by browser] right on browser + + /* "Content-Disposition : inline" will show viewable types [like images/text/pdf/anything viewable by browser] right on browser while others(zip e.g) will be directly downloaded [may provide save as popup, based on your browser setting.]*/ response.setHeader("Content-Disposition", String.format("inline; filename=\"" + file.getName() + "\"")); - + /* "Content-Disposition : attachment" will be directly download, may provide save as popup, based on your browser setting*/ //response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName())); - + response.setContentLength((int) file.length()); - + InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); - + //Copy bytes from source to destination(outputstream in this example), closes both streams. FileCopyUtils.copy(inputStream, response.getOutputStream()); } - + + private void downloadFileFromS3(File imageFile, String awsAccessKeyId, String awsSecretAccessKey, String awsRegion, + String awsBucket, String awsKeyFolder, HttpServletResponse response) throws Exception { + // client configuration optimization and socket timeout + ClientConfiguration clientConfiguration = new ClientConfiguration().withMaxErrorRetry(MAX_ERROR_RETRY) + .withMaxConnections(MAX_CONNECTIONS).withConnectionTimeout(MAX_CONNECTION_TIME_OUT) + .withSocketTimeout(SOCKET_TIME_OUT); + // instantiate s3 client with configs + AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials( + new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKeyId, awsSecretAccessKey))) + .withClientConfiguration(clientConfiguration).withRegion(awsRegion).build(); + + String mimeType = URLConnection.guessContentTypeFromName(imageFile.getName()); + if (mimeType == null) { + mimeType = "application/octet-stream"; + } + + response.setContentType(mimeType); + response.setHeader("Content-Disposition", String.format("inline; filename=\"" + imageFile.getName() + "\"")); + response.setContentLength((int) imageFile.length()); + try { + S3Object object = s3Client.getObject(new GetObjectRequest(awsBucket, awsKeyFolder + imageFile.getName())); + S3ObjectInputStream objectContent = object.getObjectContent(); + // copy input stream contents to file + FileCopyUtils.copy(objectContent, response.getOutputStream()); + object.close(); + objectContent.close(); + } + catch (AmazonServiceException aws) { + aws.printStackTrace(); + } + catch (AmazonClientException aws) { + aws.printStackTrace(); + } + catch (IOException io) { + io.printStackTrace(); + } + } + + private void setErrorMessage(HttpServletResponse response) { + String errorMessage = "Sorry. The file you are looking for does not exist"; + try { + logger.info(errorMessage); + OutputStream outputStream = response.getOutputStream(); + outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8"))); + outputStream.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + + } } diff --git a/pom.xml b/pom.xml index a6d9e6fe70..0a94882dcd 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.opensrp @@ -8,7 +8,7 @@ pom 0.1-SNAPSHOT opensrp - http://github.com/OpenSRP/opensrp-server + http://github.com/OpenSRP/opensrp-server opensrp-common @@ -24,13 +24,13 @@ ${project.basedir} - 0.11 - org.motechproject.contrib-drishti - 0.1-SNAPSHOT - UTF-8 - 3.1.0.RELEASE + 0.11 + org.motechproject.contrib-drishti + 0.1-SNAPSHOT + UTF-8 + 3.1.0.RELEASE 5.1.36 - 1.9.7 + 1.9.7 always @@ -100,269 +100,229 @@ http://nexus.motechproject.org/content/repositories/releases - - - skip-integration-tests - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.9 - - - - integration-test - verify - - - -XX:MaxPermSize=1024M - - **/it/** - - true - - - - - - - - - integration-tests - - true - - - - - - - maven-antrun-plugin - 1.6 - - - Drop DB Before Unit and Repository Tests - process-test-classes - - - - - - - - - - - - - - - - - run - - - - CREATE DB OPENSRP - pre-integration-test - - - - - - - - - - - - - run - - - - - - org.codehaus.mojo - sql-maven-plugin - 1.5 - - - - mysql - mysql-connector-java - ${mysql.connector.version} - - + + + skip-integration-tests + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.9 + + + + integration-test + verify + + + -XX:MaxPermSize=1024M + + **/it/** + + true + + + + + + + + + integration-tests + + true + - - ${jdbc.driverClassName} - ${jdbc.url-wo-db} - ${jdbc.username} - ${jdbc.password} - ${maven.test.skip} - + + + + + maven-antrun-plugin + 1.6 + + + + + org.codehaus.mojo + sql-maven-plugin + 1.5 + + + + mysql + mysql-connector-java + ${mysql.connector.version} + + - - - - drop-create-relational-db - pre-integration-test - - execute - - - ${jdbc.url-wo-db} - ${jdbc.username} - ${jdbc.password} - true - - drop database if exists ${db.quartz}; - create database ${db.quartz}; - - abort - - - - - create-quartz-tables - pre-integration-test - - execute - - - ${jdbc.url-wo-db}/${db.quartz} - ${jdbc.username} - ${jdbc.password} - true - - ../build/sql/tables_quartz_${jdbc.backend}.sql - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.9 - - - - integration-test - verify - - - -XX:MaxPermSize=1024M - - **/it/** - - true - - - - - - - - - + + ${jdbc.driverClassName} + ${jdbc.url-wo-db} + ${jdbc.username} + ${jdbc.password} + ${maven.test.skip} + + + + + + drop-create-relational-db + pre-integration-test + + execute + + + ${jdbc.url-wo-db} + ${jdbc.username} + ${jdbc.password} + true + + drop database if exists ${db.quartz}; + create database ${db.quartz}; + + abort + + + + + create-quartz-tables + pre-integration-test + + execute + + + ${jdbc.url-wo-db}/${db.quartz} + ${jdbc.username} + ${jdbc.password} + true + + ../build/sql/tables_quartz_${jdbc.backend}.sql + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.9 + + + + integration-test + verify + + + -XX:MaxPermSize=1024M + + **/it/** + + true + + + + + + + + + - - - org.apache.maven.plugins - maven-compiler-plugin - 2.5.1 - - 1.7 - 1.7 - UTF-8 - - - - org.apache.maven.plugins - maven-resources-plugin - 2.5 - - UTF-8 - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.5 - + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.7 + 1.7 + UTF-8 + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + UTF-8 + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.5 + + + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + initialize + + read-project-properties + + + + ${main.basedir}/build/maven.properties + ${main.basedir}/assets/config/opensrp.properties + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + true + + **/it/** + + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + + + + org.eluder.coveralls + coveralls-maven-plugin + 4.0.0 + - - org.codehaus.mojo - properties-maven-plugin - 1.0-alpha-2 - - - initialize - - read-project-properties - - - - ${main.basedir}/build/maven.properties - ${main.basedir}/assets/config/opensrp.properties - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.20 - - true - - **/it/** - - - - - - - org.jacoco - jacoco-maven-plugin - 0.7.9 - - ${basedir}/target/coverage-reports/jacoco-unit.exec - ${basedir}/target/coverage-reports/jacoco-unit.exec - - - - jacoco-initialize - - prepare-agent - - - - jacoco-site - test - - report - - - - - - org.eluder.coveralls - coveralls-maven-plugin - 4.0.0 - - - +