java - AWS 使用 JAVA 从 s3 对象创建新文件时出错

标签 java amazon-web-services amazon-s3 lambda geotools

我有一个形状文件,我需要从我的 Java 代码中读取该形状文件。我使用以下代码读取形状文件。

public class App {
    public static void main(String[] args) {
        File file = new File("C:\\Test\\sample.shp");
        Map<String, Object> map = new HashMap<>();//
        try {
            map.put("url", URLs.fileToUrl(file));
            DataStore dataStore = DataStoreFinder.getDataStore(map);
            String typeName = dataStore.getTypeNames()[0];
            SimpleFeatureSource source = dataStore.getFeatureSource(typeName);
            SimpleFeatureCollection collection = source.getFeatures();

            try (FeatureIterator<SimpleFeature> features = collection.features()) {
                while (features.hasNext()) {
                    SimpleFeature feature = features.next();
                    SimpleFeatureType schema = feature.getFeatureType();
                    Class<?> geomType = schema.getGeometryDescriptor().getType().getBinding();

                    String type = "";
                    if (Polygon.class.isAssignableFrom(geomType) || MultiPolygon.class.isAssignableFrom(geomType)) {

                        MultiPolygon geom = (MultiPolygon) feature.getDefaultGeometry();
                        type = "Polygon";
                        if (geom.getNumGeometries() > 1) {
                            type = "MultiPolygon";
                        }
                    } else if (LineString.class.isAssignableFrom(geomType)
                            || MultiLineString.class.isAssignableFrom(geomType)) {
                    } else {

                    }
                    System.out.println(feature.getDefaultGeometryProperty().getValue().toString());

                }
            }
        } catch (Exception e) {
            // TODO: handle exception
        }

    }
}

我得到了想要的输出。但我的要求是编写一个 aws lambda 函数来读取形状文件。为了这 1. 我创建了一个 s3 事件的 Lambda java 项目。我在 handleRequest 中编写了相同的代码。我将 java lambda 项目作为 lanbda 函数上传并添加了一个触发器。当我将 .shp 文件上传到 as s3 存储桶时,lmbda 函数将自动调用。但是我收到如下错误

java.lang.RuntimeException: java.io.FileNotFoundException: /sample.shp (No such file or directory)

我的 s3 存储桶中有 sample.shp 文件。我通过下面的链接。 How to write an S3 object to a file?

我遇到了同样的错误。我尝试像下面这样更改我的代码

  S3Object object = s3.getObject(new GetObjectRequest(bucket, key)); 
  InputStream objectData = object.getObjectContent();
  map.put("url", objectData );

代替

File file = new File("C:\\Test\\sample.shp"); 
 map.put("url", URLs.fileToUrl(file));

:-( 现在我收到如下错误

java.lang.NullPointerException

我也尝试了下面的代码

DataStore dataStore = DataStoreFinder.getDataStore(objectData);

代替

DataStore dataStore = DataStoreFinder.getDataStore(map);

错误如下

java.lang.ClassCastException: com.amazonaws.services.s3.model.S3ObjectInputStream cannot be cast to java.util.Map

我还尝试将键直接添加到 map 以及作为 DataStore 对象。一切都出错了..:-(

有没有人可以帮助我? 如果有人能帮我做这件事,那将非常有帮助...

最佳答案

DataStoreFinder.getDataStore geotools 中的方法要求您提供包含键/值对和键“url”的映射。与该“url”键关联的值需要是一个文件 URL,如“file://host/path/my.shp”。

您正在尝试将 Java 输入流插入到 map 中。那行不通,因为它不是文件 URL。

geotools 库不接受 http/https URL(请参阅 geotools 代码 herehere ),因此您需要一个 file://URL。这意味着您需要将文件从 S3 下载到本地 Lambda 文件系统,然后提供指向该本地文件的 file://URL。为此,这里是应该工作的 Java 代码:

// get the shape file from S3 to local filesystem
File localshp = new File("/tmp/download.shp");
s3.getObject(new GetObjectRequest(bucket, key), localshp);

// now store file:// URL in the map
map.put("url", localshp.getURI().getURL().toString());

如果 geotools 库接受了真实的 URL(而不仅仅是 file://URL),那么您就可以避免下载并简单地为 S3 对象创建一个限时的预签名 URL 并将该 URL 放入 map 中.

这是一个如何做到这一点的例子:

// get current time and add one hour
java.util.Date expiration = new java.util.Date();
long msec = expiration.getTime();
msec += 1000 * 60 * 60;
expiration.setTime(msec);

// request pre-signed URL that will allow bearer to GET the object
GeneratePresignedUrlRequest gpur = new GeneratePresignedUrlRequest(bucket, key);
gpur.setMethod(HttpMethod.GET);
gpur.setExpiration(expiration);

// get URL that will expire in one hour
URL url = s3.generatePresignedUrl(gpur);

关于java - AWS 使用 JAVA 从 s3 对象创建新文件时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48208491/

相关文章:

java - 更改 Facebook SDK 请求对话框标题和通知标题

点和框游戏的 Java minimax

reactjs - 刷新页面时Cloudfront返回403禁止

amazon-web-services - AWS S3存储桶不一致

amazon-web-services - `aws eks list-nodegroups`和 `eksctl get nodegroups`结果不一致

ios - 带有 iOS 圆形进度条的 AWS S3 下载

java - Android内部类中EditText转int

java - 如何查看Hashmap的第一个元素?

amazon-web-services - 无法将导入的证书选择到 AWS 负载均衡器监听器中

amazon-web-services - 使用 amazon sagemaker python SDK 与 AWS SDK for python (Boto3) 有什么区别