Skip to content

Instantly share code, notes, and snippets.

@arthurportas
Last active July 27, 2022 00:36
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arthurportas/7b6e5ffb413a507fb84c to your computer and use it in GitHub Desktop.
Save arthurportas/7b6e5ffb413a507fb84c to your computer and use it in GitHub Desktop.
Sample configuration Spring-Cloud-AWS, File services and Controller
#sample cli request using curl
curl -i -F name=original_file_name_travelling_to_aws.txt -F filedata=@dummy.jpg http://localhost:8080/upload
#This assumes you're running curl inside directory where 'dummy.jpg' is.
#aws final file name is returned inside S3Object.getKey()
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import org.springframework.cloud.aws.context.config.annotation.EnableContextCredentials;
import org.springframework.cloud.aws.context.config.annotation.EnableContextResourceLoader;
import org.springframework.cloud.aws.context.support.io.ResourceLoaderBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@Configuration
@EnableContextResourceLoader
@EnableContextCredentials
public class Configuration {
//TODO: these values should be read from config
private static final String ACCESS_KEY = "XXX";
private static final String SECRET_KEY = "YYY";
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public AmazonS3Client amazonS3Client() {
return new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
}
@Bean
public ResourceLoaderBeanPostProcessor resourceLoaderBeanPostProcessor() {
return new ResourceLoaderBeanPostProcessor(amazonS3Client());
}
}
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
public class AbstractFileController {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFileController.class);
@Autowired
private FileUploadService fileUploadService;
@Autowired
private FileDownloadService fileDownloadService;
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public void uploadFile(@RequestParam("file") MultipartFile file, String bucketName) {
S3Object s3Object = null;
if (!file.isEmpty()) {
LOGGER.debug("File name:" + file.getOriginalFilename());
try {
s3Object = fileUploadService.writeFile(file.getInputStream(), bucketName);
LOGGER.debug("File uploaded with name:" + s3Object.getKey());
} catch (IOException ioe) {
LOGGER.debug(ioe.getMessage());
}
}
}
@RequestMapping(value = "/download", method = RequestMethod.GET)
@ResponseBody
public void downloadFile(@RequestParam("name") String awsFileName, HttpServletResponse response, String bucketName) {
LOGGER.debug("Downloading file with name:" + awsFileName);
try {
addDownloadResponseHeaders(response, awsFileName);
IOUtils.copy(fileDownloadService.readFile(awsFileName, bucketName), response.getOutputStream());
} catch (IOException ioe) {
LOGGER.debug(ioe.getMessage());
}
}
private void addDownloadResponseHeaders(HttpServletResponse response, String clientKnownFileName) {
response.setHeader("Content-type", "text/csv");//this use case is only for csv files
response.setHeader("Content-Disposition", "attachment; filename=\"" + clientKnownFileName + "\"");
response.setHeader("Content-Transfer-Encoding", "binary");
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
@Service
public class FileDownloadServiceImpl {
private static final String S3_PREFIX = "s3://";
@Autowired
private ResourceLoader resourceLoader;
@Override
public InputStream readFile(String fileName, String bucketName) throws IOException {
Resource resource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/" + fileName);
return resource.getInputStream();
}
}
import com.amazonaws.services.s3.AmazonS3Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FileRemovalServiceImpl implements FileRemovalService {
private static final String S3_PREFIX = "s3://";
@Autowired
private AmazonS3Client amazonS3Client;
@Override
public void removeFile(String fileName, String bucketName) throws Exception {
this.amazonS3Client.deleteObject(bucketName, fileName);
}
}
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.WritableResource;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@Service
public class FileUploadServiceImpl {
private static final String S3_PREFIX = "s3://";
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private AmazonS3Client amazonS3Client;
public S3Object writeFile(File file, String bucketName) throws IOException {
String uniqueFileName = FileUtils.generateRandomFileId();
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, uniqueFileName, file);
PutObjectResult putObjectResult = this.amazonS3Client.putObject(putObjectRequest);
return this.amazonS3Client.getObject(bucketName, uniqueFileName);
}
public S3Object writeFile(InputStream is, String bucketName) throws IOException {
String uniqueFileName = FileUtils.generateRandomFileId();
Resource resource = this.resourceLoader.getResource(S3_PREFIX + bucketName + "/" + uniqueFileName);
WritableResource writableResource = (WritableResource) resource;
try (OutputStream outputStream = writableResource.getOutputStream()) {
outputStream.write(IOUtils.toByteArray(is));
}
return this.amazonS3Client.getObject(bucketName, uniqueFileName);
}
}
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.UUID;
public class FileUtils {
private static String UNDERSCORE = "_";
public static String generateRandomFileId() {
return new StringBuilder()
.append(UUID.randomUUID().toString())
.append(UNDERSCORE)
.append(ZonedDateTime.now(ZoneId.of("UTC")))
.toString();
}
public static String generateRandomFileId(String fileName) {
return new StringBuilder()
.append(fileName)
.append(UNDERSCORE)
.append(UUID.randomUUID().toString())
.append(UNDERSCORE)
.append(ZonedDateTime.now(ZoneId.of("UTC")))
.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment