Amazon S3 Resource Locator Example - skremp/pictura-io GitHub Wiki
As of PicturaIO 1.1.2 it is possible to connect to an existing Amazon S3 bucket with its own credentials and a custom resource locator. To handle this, we have to provide a S3ResourceLocator
which will convert a requested image resource path to an java.net.URL
object and a java.net.URLStreamHandler
to handle the new URL protocol s3
. If this is done, the io.pictura.servlet.ImageRequestProcessor
can reading files from Amazon S3 directly in a java.net.URL
object without any change or modification of the core request processor.
Our own io.pictura.servlet.ResourceLocator
to create a valid java.net.URL
object from a requested resource (source image) path.
package io.pictura.servlet.s3;
import io.pictura.servlet.ResourceLocator;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
public class S3ResourceLocator implements ResourceLocator {
// Custom Amazon S3 Credentials
private static final String ACCESS_KEY = ...;
private static final String SECRET_KEY = ...;
private static final String BUCKET = ...;
// Register the new protocol handler package
static {
String pkgs = System.getProperty("java.protocol.handler.pkgs");
if (pkgs == null || pkgs.isEmpty()) {
System.setProperty("java.protocol.handler.pkgs",
"io.pictura.net.protocol");
} else if (!pkgs.contains("io.pictura.net.protocol")) {
System.setProperty("java.protocol.handler.pkgs",
pkgs + "|io.pictura.net.protocol");
}
}
@Override
public URL getResource(String path) throws MalformedURLException {
if (path != null && !path.isEmpty()) {
String str = path.toLowerCase(Locale.ENGLISH);
if (str.startsWith("s3://") && str.length() > 5) {
return new URL("s3://" + ACCESS_KEY + ":" + SECRET_KEY +
"@" + BUCKET + ".s3.amazonaws.com/" + path.substring(5));
}
}
return null;
}
}
A custom java.net.URLStreamHandler
to handle connections to Amazon S3 URL's so we are able to reading files from Amazon S3 directly in a java.net.URL
object.
package io.pictura.net.protocol.s3;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
public final class Handler extends URLStreamHandler {
@Override
protected URLConnection openConnection(URL u) throws IOException {
// "s3://<access-key>:<secret-key>@<bucket>.s3.amazonaws.com/<filename>"
return new URLConnection(u) {
@Override
public InputStream getInputStream() throws IOException {
String accessKey = null;
String secretKey = null;
if (url.getUserInfo() != null) {
String[] credentials = url.getUserInfo().split("[:]");
accessKey = credentials[0];
secretKey = credentials[1];
}
String bucket = url.getHost().substring(0, url.getHost().indexOf("."));
String key = url.getPath().substring(1);
InputStream is = null;
try {
RestS3Service s3Service = new RestS3Service(
new AWSCredentials(accessKey, secretKey));
S3Object s3obj = s3Service.getObject(
new S3Bucket(bucket), key);
is = s3obj.getDataInputStream();
} catch (S3ServiceException e) {
throw new IOException(e);
}
return is;
}
@Override
public void connect() throws IOException { }
};
}
}
Now, we can register our custom Amazon S3 resource locator as described in the PicturaIO Image Servlet API Reference, like:
<web-app ...>
...
<servlet>
...
<init-param>
<param-name>resourceLocators</param-name>
<param-value>
io.pictura.servlet.s3.S3ResourceLocator,
io.pictura.servlet.HttpResourceLocator,
io.pictura.servlet.FileResourceLocator
</param-value>
</init-param>
</servlet>
...
</web-app>