Reading shape files from zip using absolute path

I have a zip of shape files containing following files.

  1. Nodes_1.dbf
  2. Nodes_1.prj
  3. Nodes_1.shp
    4.Nodes_1.shx
    5.Pipes_1.dbf
    6.Pipes_1.prj
    7.Pipes_1.shp
    8.Pipes_1.shx

I am trying to open files from zip but getting error invalid shape files.
var files = Request.Form.Files;
foreach (var file in files)
{
{

                var inputFilepath = AbstractPath.FromStream(file.OpenReadStream());

                var layer = VectorLayer.Open(file.FileName, Drivers.Shapefile);
            }
        }

If if am trying to convert or open files individually getting error
“.SHX file is missing”.
Please help me with the correct way of reading files.
I want to extract data from this.
Thanks

Hi, @pranav.mishra

Thank you for your interest in the Aspose.GIS product.

In order to make Aspose.GIS work with the zip in memory, an inheritor of Aspose.Gis.AbstractPath must be implemented. This forum note contains an example of such inheritor and how to use it.

Please feel free to contact us if you have any other issues or difficulty using the product.

Hi @Evgeniy.Timofeev ,
Let me tell you my requirement from scratch.
I am looking to convert Nodes_1.zip (18.9 KB)
I am trying to convert attached shape files to json in order to read their data.
My API accepts files into form collection of http request.
When I an trying to do VectorLayer.Convert(inputFilepath, Drivers.Shapefile, outputfilename1, Drivers.GeoJson); it gives me error “Missingn .SHX file” while .shx file is in the form collection.
Since I am new to it I really do not know how to get it done. Share me some working example. I can’t use string file path as it is not from local but from a hosted environment.

The best way is to save your http request data to files on disk and then use the below code.

        var dataFolder = @"C:\Downloads\Nodes_1\";
        
        using (var layer = Drivers.Shapefile.OpenLayer(Path.Combine(dataFolder, "Nodes_1.shp")))
        {
            // copy columns info
            Console.WriteLine(layer.Count);
        }

Use the other way if you need to work only in memory . Please copy your http request data for each file to own memory stream.

        // Add the streams in dictionary
        // I don't have http request data so I use for example streams from file. 
        var storage = new Dictionary<string, Stream>();
        storage.Add("Nodes_1.shp", new FileStream(Path.Combine(dataFolder, "Nodes_1.shp"), FileMode.Open));
        storage.Add("Nodes_1.shx", new FileStream(Path.Combine(dataFolder, "Nodes_1.shx"), FileMode.Open));
        storage.Add("Nodes_1.dbf", new FileStream(Path.Combine(dataFolder, "Nodes_1.dbf"), FileMode.Open));
        storage.Add("Nodes_1.prj", new FileStream(Path.Combine(dataFolder, "Nodes_1.prj"), FileMode.Open));

        // read using MultiStreamPath
        using (var multiStreamPath = new MultiStreamPath("Nodes_1.shp", storage))
        using (var layer = Drivers.Shapefile.OpenLayer(multiStreamPath))
        {
            // copy columns info
            Console.WriteLine(layer.Count);
        }

        Console.ReadKey();

Implementation of MultiStreamPath

    public class MultiStreamPath : AbstractPath, IDisposable
    {
        private readonly string _entryName;
        private readonly Dictionary<string, Stream> _storage;
        private readonly List<Stream> _streams = new List<Stream>();

        public MultiStreamPath(string entryName, Dictionary<string, Stream> storage)
        {
            this._storage = storage;
            _entryName = entryName;
        }

        public override bool IsFile()
        {
            // In our terms, if there is a entry on our stream list, we return true.
            return this._storage.ContainsKey(this._entryName);
        }

        public override void Delete()
        {
            this._storage.Remove(this._entryName);
        }

        public override Stream Open(FileAccess access)
        {
            var stream = this._storage[this._entryName];
            var openedStream = AbstractPath.FromStream(stream).Open(access);
            this._streams.Add(openedStream);
            return openedStream;
        }

        public override IEnumerable<AbstractPath> ListDirectory()
        {
            var list = new List<AbstractPath>();
            foreach (var item in this._storage)
            {
                list.Add(new MultiStreamPath(item.Key, this._storage));
            }

            return list;
        }

        public void Dispose()
        {
            foreach (var stream in this._streams)
            {
                stream?.Dispose();
            }
        }

        protected override AbstractPath WithLocation(string newLocation)
        {
            return new MultiStreamPath(newLocation, this._storage);
        }

        public override string Location => this._entryName;
        public override char Separator => '/';
    }

Best Regards