AWS Создание новых файлов из объекта s3 с использованием ошибки получения JAVA
У меня есть файл формы, и мне нужно прочитать файл формы из моего кода 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 для чтения файла формы. Для этого 1. Я создал Java-проект Lambda для события s3. Я написал тот же код внутри handleRequest. Я загрузил Java-лямбда-проект как функцию lanbda и добавил один триггер. Когда я загружаю файл.shp в качестве s3, автоматически запускается функция lmbda. Но я получаю ошибку, как показано ниже
java.lang.RuntimeException: java.io.FileNotFoundException: /sample.shp (нет такого файла или каталога)
У меня есть файл sample.shp внутри моей корзины s3. Я иду по ссылке ниже. Как записать объект S3 в файл?
Я получаю ту же ошибку. Я пытался изменить свой код, как показано ниже
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
Также я попытался добавить ключ непосредственно на карту, а также в качестве объекта хранилища данных. Все пошло не так..:-(
Есть кто-нибудь, кто может мне помочь? Будет очень полезно, если кто-то сможет сделать это для меня...
1 ответ
Метод DataStoreFinder.getDataStore в geotools требует, чтобы вы предоставили карту, содержащую пару ключ / значение с ключом "url". Значение, связанное с этим ключом "url", должно быть URL-адресом файла, например "file: //host/path/my.shp".
Вы пытаетесь вставить поток ввода Java в карту. Это не сработает, потому что это не файл URL.
Библиотека geotools не принимает URL-адреса http / https (см. Код geotools здесь и здесь), поэтому вам нужен файл:// URL. Это означает, что вам нужно будет загрузить файл из S3 в локальную файловую систему Lambda, а затем предоставить файл: // 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: // URLs), вы могли бы избежать загрузки и просто создать ограниченный по времени предварительно подписанный URL для объекта S3 и поместить этот 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);