Skip navigation

Geo-tag Your Photos Using ASP.NET and Google Maps: Part II

Upload, Tag, Save, and Retrieve Photos

asp:Feature

LANGUAGES: JavaScript

ASP.NET VERSIONS: 2.0

 

Geo-tag Your Photos Using ASP.NET and Google Maps: Part II

Upload, Tag, Save, and Retrieve Photos

 

By Wei-Meng Lee

 

In Part I, you learned how to embed Google Maps into your ASP.NET Web applications, how you can interact with the maps by adding markers, and how to search for locations. In this installment, we ll extend the project created in Part I so users can upload photos to it and geo-tag each photo using Google Maps.

 

Uploading Photos

The first step is to create a new folder in your project so users can upload their photos. In Solution Explorer, right-click on the project name and select New Folder. Name the new folder Uploads (see Figure 1).

 


Figure 1: Create the new Uploads folder.

 

Next, add a new Web Form to the project and name it UploadPhotos.aspx. In the Source View of UploadPhotos.aspx, add a FileUpload control and a Button control, as shown in bold here:

 

 

 Upload Photos

 

 

 

   Width="76px" />

 

 

Figure 2 shows the page in Design view. As you can see, the FileUpload control allows users to upload photos to the Web application. You ll also add a ListBox control to the page, so you can list the filenames of all the photos available in the Uploads folder. When the user clicks on a filename in the ListBox control, you ll use an Image control to display the photo (see Figure 3). Figure 4 shows how UploadPhotos.aspx should look.

 


Figure 2: Use the FileUpload control to upload photos to the site.

 

 Upload Photos

 

 

    Width="76px" />

 

   

     

     

   

 

         Photos

         

            AutoPostBack="True" Height="306px"

            Width="149px">

         

     

         

          Height="324px" Width="432px" />

     

Figure 3: Use an Image control to display the photo.

 


Figure 4: Populate the UploadPhotos.aspx page with various controls.

 

Switching to the code-behind of UploadPhoto.aspx, first import the following namespace:

 

Imports System.IO

 

Define the ListPhotos subroutine so it will list all the filenames of the photos stored within the Uploads folder (see Figure 5).

 

Private Sub ListPhotos()

 Dim photos As String() = _

   Directory.GetFiles(Request.PhysicalApplicationPath & _

   "Uploads")

 lstPhotos.Items.Clear()

 For Each photo As String In photos

    Dim item As New ListItem

    With item

      .Text = photo.Substring(photo.LastIndexOf("\") + 1)

      .Value = photo.Substring(photo.LastIndexOf("\") + 1)

    End With

    lstPhotos.Items.Add(item)

 Next

End Sub

Figure 5: List all the filenames of photos stored in the Uploads folder.

 

Define the click event handler for the Upload button so users can upload photos to the Uploads folder (see Figure 6).

 

Protected Sub btnUpload_Click( _

 ByVal sender As Object, _

 ByVal e As System.EventArgs) _

 Handles btnUpload.Click

  Dim savepath As String = Request.PhysicalApplicationPath

  savepath += "Uploads\"

  If FileUpload1.HasFile Then

      savepath += FileUpload1.FileName

      FileUpload1.SaveAs(savepath)

      Response.Write("Uploading done!")

  End If

  ListPhotos()

End Sub

Figure 6: Upload a photo to the Uploads folder.

 

When a user clicks on a filename in the ListBox control, the image is displayed using the Image control. This is handled by the lstPhotos_SelectedIndexChanged subroutine:

 

Protected Sub lstPhotos_SelectedIndexChanged( _

 ByVal sender As Object, _

 ByVal e As System.EventArgs) _

 Handles lstPhotos.SelectedIndexChanged

  imgPhoto.ImageUrl = "./Uploads/" & lstPhotos.SelectedValue

End Sub

 

Finally, invoke the ListPhotos subroutine when the page is loaded:

 

Protected Sub Page_Load( _

 ByVal sender As Object, _

 ByVal e As System.EventArgs) _

 Handles Me.Load

  If Not IsPostBack Then

      ListPhotos()

  End If

End Sub

 

Press F5 in Visual Studio 2005. You can upload a photo and view photos by clicking on the ListBox control (see Figure 7).

 


Figure 7: View the uploaded photos.

 

Geo-tagging Photos

The next step is to allow users to geo-tag photos from the Uploads folder. In the Source View of Default.aspx, add a table and populate it with the controls shown in Figure 8; Figure 9 shows the new controls.

 

  EnablePartialRendering="true">

 

    

    

 

 

    

 

       

       

    

       

         Height="538px" Width="205px"

         ScrollBars="Vertical">

       

    

       

          

             Filename    

             

                Width="150px">

             

             Description

            

                runat="server"

                Width="200px" Height="55px"

                TextMode="MultiLine">

             

             

                OnClientClick="AddPhoto()"

                Text="Add Photo"

                Width="104px" />

          

       

    

Latitude

...

Figure 8: Add a table and populate it with these controls.

 


Figure 9: The Default.aspx page with additional controls.

 

The Panel control is used to display the photos stored in the Uploads folder. Users can then select the photos they want to add to the map (by clicking on the photos) and the selected filename will appear in the TextBox control (under the Filename label). Users can also add a description for the photo. Once this is done, clicking the Add Photo button will add the selected photo to Google Maps.

 

Switch to the code-behind of Default.aspx and add the following namespace:

 

Imports System.IO

 

Next, define the LoadPhotos subroutine so you can display all the photos stored in the Uploads folder by dynamically creating new ImageButton controls and adding them to the Panel control (see Figure 10).

 

Private Sub LoadPhotos()

 '---get the list of photos in the Uploads directory---

 Dim photos As String() = _

   Directory.GetFiles(Request.PhysicalApplicationPath & _

   "Uploads")

 For Each photo As String In photos

    Dim img As New ImageButton

    With img

      .ImageUrl = "./Uploads/" & _

         photo.Substring(photo.LastIndexOf("\") + 1)

      .Width = 200

      .Height = 150

      .BorderStyle = BorderStyle.Double

      .BorderWidth = 4

      '---use the filename as the alternate text---

      .AlternateText = photo.Substring( _

         photo.LastIndexOf("\") + 1)

      .Attributes.Add("onclick", "display_filename('" & _

         photo.Substring( _

         photo.LastIndexOf("\") + 1) & "'); return false")

    End With

    '---add the image control to the Panel control---

    Panel1.Controls.Add(img)

 Next

End Sub

Figure 10: Display photos stored in the Uploads folder.

 

Each ImageButton control added to the Panel control has the filename (of its photo) stored in the AlternateText property. Also, an event (onclick) handler is attached to all ImageButton controls. This is to allow users to select an image so the filename of the selected image can be displayed in one of the TextBox controls. And because the ImageButton control is an ASP.NET server control, you must add the ; return false sentence to prevent a postback from occurring when the user clicks on an image:

 

.Attributes.Add("onclick", "display_filename('" & _

  photo.Substring( _

  photo.LastIndexOf("\") + 1) & "'); return false")

 

In the Page_Load event of Default.aspx, invoke the LoadPhotos subroutine so photos can be displayed when the page is loaded:

 

Protected Sub Page_Load( _

  ByVal sender As Object, _

  ByVal e As System.EventArgs) _

  Handles Me.Load

   '---load the available photos---

   LoadPhotos()

End Sub

 

Getting back to the Source View of Default.aspx, let s now define the necessary JavaScript functions. The display_filename JavaScript function is defined as follows:

 

//---display the name of the selected photo---

function display_filename(filename) {

  document.forms[0].txtFileName.value=filename;

}

 

This function is invoked when the user clicks on an ImageButton control in the Panel control. The next function to define is AddPhoto, which is invoked when the user clicks the Add Photo button (see Figure 11).

 

function AddPhoto()

{

 //---HTML for displaying the photo---

 var content = '

     Height="225" src="./Uploads/' +

    document.forms[0].txtFileName.value + '" />';

 //---create the info tabs---

 var infoTabs = [

    new GInfoWindowTab("Photo", content),

    new GInfoWindowTab("Description",

       document.forms[0].txtDescription.value)

 ];

 //---set the location to add the photo---

 var centerPoint = new GPoint(

    document.forms[0].txtLongitude.value,

    document.forms[0].txtLatitude.value);

 //---create a new marker object---

 var marker = new GMarker(centerPoint);

 //---add the click event for the marker---

 GEvent.addListener(marker, "click",

 function() {

    //---open the marker info tab---

    marker.openInfoWindowTabsHtml(infoTabs);

 });

 //---add the marker---

 map.addOverlay(marker);

 //---open the marker info tab---

 marker.openInfoWindowTabsHtml(infoTabs);

}

Figure 11: Define the AddPhoto function.

 

Here, a marker is inserted on the map when the user clicks the Add Photo button. A balloon containing two tabs will appear the first tab displays the photo selected; the second tab displays the description given by the user.

 

You are now ready to test the application. Press F5 in Visual Studio 2005. Figure 12 shows the Panel control listing all the photos stored in the Uploads folder (assuming you uploaded photos to it). You can select a photo, give it a description, then click the Add Photo button to add it to the map (see Figure 13).

 


Figure 12: View all the photos stored in the Uploads folder.

 


Figure 13: Geo-tag a photo.

 

Saving the Tagged Photos

You now know how to geo-tag photos by adding them to Google Maps. However, all the markers disappear when you reload the page. This is because Google Maps doesn t persist the markers you must devise your own mechanism to save the markers.

 

To save the geo-tagged photos, you must save to a text file located on the server the positional information (latitude and longitude), filename, and description. This can be done via the click event handler for the Add Photo button (remember, it s an ASP.NET Server control, so there s a server-side event handler). For simplicity, save the information of each photo into a text file when the user adds a photo to the map (see Figure 14).

 

Protected Sub btnAddPhoto_Click( _

   ByVal sender As Object, _

   ByVal e As System.EventArgs) _

   Handles btnAddPhoto.Click

   '---Save as: Lat, Lng, FileName, Description---

   Dim str As String = txtLatitude.Text & "," & _

                       txtLongitude.Text & "," & _

                       txtFileName.Text & "," & _

                       txtDescription.Text & vbCrLf

   '---save it to file---

   My.Computer.FileSystem.WriteAllText("c:\photos.txt",

       str, True)

   '---clear the FileName and Description TextBoxes---

   txtFileName.Text = ""

   txtDescription.Text = ""

End Sub

Figure 14: Save the information of each photo into a text file.

 

Each line in the text file contains information for each geo-tagged photo, in the following format:

 

latitude, longitude, filename, description

 

The typical content of the text file looks like this:

 

37.649305852772585,-122.43026733398437,

 DSC00452.JPG,This is our first stop.

37.68612977745383,-122.39765167236328,

 DSC00455.JPG,This is where we had our lunch.

 

Now that we can save the geo-tagged photos, the next thing to do is load the geo-tagged photos every time the user loads the page. For this, use a Web service hosted on the server so the client can request the list of geo-tagged photos and add it asynchronously to the page.

 

First, add a new Web service file to the current project (right-click on the project name in Solution Explorer, then select Add New Item; select the Web Service template). Use the default name of WebService.asmx. In the code-behind of WebService.asmx, import the following namespace:

 

Imports System.IO

 

Then, populate it with the code shown in bold in Figure 15. Essentially, the GetTaggedPhotos function returns the content of the text file containing the geo-tagged photos.

 

_

_

_

_

Public Class WebService

   Inherits System.Web.Services.WebService

   Const FILE_NAME = "c:\photos.txt"

    _

   Public Function GetTaggedPhotos() As String

       Dim fileContents As String

       If File.Exists(FILE_NAME) Then

           fileContents = _

              My.Computer.FileSystem.ReadAllText(FILE_NAME)

           Return fileContents

       Else

           Return String.Empty

       End If

   End Function

End Class

Figure 15: Retrieve the contents of the text file containing geo-tagged photos.

 

Back in the Default.aspx page, add the AddTaggedPhoto JavaScript function so you can call the Web method from the client side:

 

//---add the tagged photo to the map---

function AddTaggedPhoto()

{

  //---get the points from the Web service---

  req = WebService.GetTaggedPhotos(onComplete);

}

 

Add the element to the ScriptManager control to be able to call a Web service asynchronously from the client using JavaScript, as shown here:

 

  EnablePartialRendering="true">

   

       

   

 

When the Web service returns the result, the onComplete JavaScript function will be invoked (as defined in Figure 16).

 

//---the result returned by the Web service---

function onComplete(result)

{

  //---split the results into individual lines---

  var lines = result.split("\r\n");

  for (i=0; i

     //---split the line into individual fields---

     var fields = lines[i].split(",");

     //---lat---

     document.forms[0].txtLatitude.value = fields[0];

     //---lng---

     document.forms[0].txtLongitude.value = fields[1];

     //---filename---

     document.forms[0].txtFileName.value = fields[2];

     //---Description---

     document.forms[0].txtDescription.value = fields[3];

     //---Add the photo to the map---

     AddPhoto();

  }

  //---clear the FileName and Description TextBoxes---

  document.forms[0].txtFileName.value = "";

  document.forms[0].txtDescription.value = "";

}

Figure 16: Invoke the onComplete JavaScript function.

 

Here, you need to break down the content of the text file into separate lines, then individually by fields. Finally, add each photo to the map by calling the AddPhoto JavaScript function. Call the AddTaggedPhoto JavaScript function in the load JavaScript function to display the geo-tagged photos every time the page is loaded (see Figure 17).

 

function load() {

 if (GBrowserIsCompatible()) {

   map = new GMap2(document.getElementById("map"));

   //---display navigational controls---

   map.addControl(new GSmallMapControl());

   //---display Map/Satellite/Hybrid---

   map.addControl(new GMapTypeControl());

   //---fired when the map is dragged---

   GEvent.addListener(map, "moveend",

      function()

      {

         var center = map.getCenter();

         //---update the lat and lng in the TextBox controls---

         document.forms[0].txtLatitude.value = center.lat();

         document.forms[0].txtLongitude.value = center.lng();

      }

   );

   //---display a particular location on the map---

   map.setCenter(new GLatLng(37.65528588731535,

                 -122.40726470947265), 13);

   //---load the previously tagged photos---

   AddTaggedPhoto();

 }

}

Figure 17: Call AddTaggedPhoto in the load JavaScript function to display the geo-tagged photos.

 

That s it! Press F5 in Visual Studio 2005 to test the application and geo-tag your photos. Once it s done, you can reload the page and verify that all the previously geo-tagged photos are still visible on the map (see Figure 18).

 


Figure 18: Display all the previously geo-tagged photos when the page is loaded/reloaded.

 

Conclusion

To wrap up this two-part series on using the Google Maps for geo-tagging, you learned how to upload files to the server and geo-tag them with Google Maps. In addition, you ve made use of AJAX to asynchronously retrieve the previously geo-tagged photos from the server so these photos are always loaded when the user loads the page.

 

The source code accompanying this article is available for download.

 

Wei-Meng Lee (http://weimenglee.blogspot.com) is a Microsoft MVP and founder of Developer Learning Solutions (http://www.learn2develop.net), a technology company specializing in hands-on training on the latest Microsoft technologies. He is an established developer and trainer specializing in .NET and wireless technologies. Wei-Meng speaks regularly at international conferences and has authored and co-authored numerous books on .NET, XML, and wireless technologies. He writes extensively on topics ranging from .NET to Mac OS X. He is also the author of.NET Compact Framework Pocket Guide, ASP.NET 2.0: A Developer s Notebook (both from O Reilly Media, Inc), and Programming Sudoku (Apress).

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish