AWS使用JAVA从s3对象创建新文件时收到错误

时间:2018-01-11 13:43:17

标签: 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函数来读取shape文件。为了这 1.我创建了一个s3事件的Lambda java项目。我在handleRequest中编写了相同的代码。我将java lambda项目作为lanbda函数上传并添加了一个触发器。当我将.shp文件上传到s3时,lmbda函数会自动调用。但我收到如下错误

  

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

我的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无法强制转换为   java.util.Map

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

有没有人可以帮助我? 如果有人能为我做这件事会非常有帮助......

1 个答案:

答案 0 :(得分:2)

地理工具中的DataStoreFinder.getDataStore方法要求您提供包含键/值对的地图,其中包含键“url”。与“url”键关联的值必须是文件URL,如“file://host/path/my.shp”。

您正在尝试将Java输入流插入到地图中。这不起作用,因为它不是文件URL。

geotools库不接受http / https网址(请参阅地理工具代码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放入地图中

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

// 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);