AWS使用JAVA从s3对象创建新文件获取错误

Sha*_*Ram 5 java lambda amazon-s3 amazon-web-services 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
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

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

java.lang.RuntimeException: java.io.FileNotFoundException: /sample.shp(没有这样的文件或目录)

我的 s3 存储桶中有 sample.shp 文件。我通过下面的链接。 如何将 S3 对象写入文件?

我收到同样的错误。我试图改变我的代码如下

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

代替

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

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

java.lang.NullPointerException

我也试过下面的代码

DataStore dataStore = DataStoreFinder.getDataStore(objectData);
Run Code Online (Sandbox Code Playgroud)

代替

DataStore dataStore = DataStoreFinder.getDataStore(map);
Run Code Online (Sandbox Code Playgroud)

错误如下

java.lang.ClassCastException:com.amazonaws.services.s3.model.S3ObjectInputStream 无法转换为 java.util.Map

我也尝试将键直接添加到地图中,也作为 DataStore 对象。一切都错了..:-(

有没有人可以帮助我?如果有人可以为我做这将非常有帮助......

jar*_*mod 2

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

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

geotools 库不接受 http/https URL(请参阅此处此处的 geotools 代码),因此您需要一个 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());
Run Code Online (Sandbox Code Playgroud)

如果 geotools 库接受真实 URL(而不仅仅是 file:// URL),那么您可以避免下载,只需为 S3 对象创建一个有时间限制的预签名 URL,并将该 URL 放入地图中。

以下是如何执行此操作的示例:

// 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);
Run Code Online (Sandbox Code Playgroud)