Uploading myNews Files: From the Browser to the Server

So far, although we've used some new approaches, we really haven't seen anything new from a technical standpoint.

When we set up the News section of mySpace, we had planned to simply link to files that were on the server instead of storing entire news articles in the database. That's great for the database, but it means that to maintain this section, we're going to have to be able to upload files to the server and remove them when we're done with them.

GEEK SPEAK: Upload means to move something from your computer to another computer. This is the opposite of downloading, which is to take something from another computer and put it on your own.

Uploading files isn't something that's included in ASP as a matter of course, but there are numerous components out there that we can use to help us out. As you may remember, there was even a trial version of one installed with ASPEmail, ASPUpload. We're going to use that to take a look at some of the issues involved with uploading files to our site.

The basic process is the same as it was for editing the links table, so let's start by making a copy of those pages. Copy edit_links.asp, edit_links_action.asp, edit_links_rec.asp, and edit_links_rec_action.asp to edit_news.asp, edit_news_action.asp, edit_news_rec.asp, and edit_links_rec_action.asp, respectively.

Let's start with edit_news.asp (see Listing 8.12).

Code Listing 8.12. edit_news.asp: Selecting news items to delete
0: <%@ LANGUAGE="VBSCRIPT" %>
1: <!--#include file="adovbs.inc"-->
2: <!--#include file="pagetop.txt"-->
3: <!--#include file="isadmin.inc"-->
4: <%
5: if isAdmin then
6: %>
7: <CENTER>
8: <H2> Edit News</h2>
9:
10:<A HREF="edit_news_rec.asp">Create a New Record</A>
11:<FORM ACTION="edit_news_action.asp" METHOD="post">
12:
13:<TABLE BORDER="1">
14:<%
15:  set outpostDB = Server.CreateObject("ADODB.Connection")
16:  outpostDB.Open "outpost"
17:
18:  set catSet = Server.CreateObject("ADODB.RecordSet")
19:  catSet.Open "news_categories", outpostDB, adOpenStatic, _

20:      adLockReadOnly, adCmdTable
21:
22:  set tableSet = Server.CreateObject("ADODB.RecordSet")
23:  tableSet.Open "select * from news order by news_id", _
24:      outpostDB, adOpenForwardOnly, adLockReadOnly, adCmdText
25:
26:  while not tableSet.EOF
27:%>      <TR>
28:      <TD>
29:          <INPUT TYPE="checkbox" NAME="p_delete"
30:               VALUE="<%=tableSet("news_id")%>">
31:      </TD>
32:<%      p_numberOfColumns = tableSet.Fields.Count
33:%>      <TD>
34:          <A HREF="edit_news_rec.asp?p_news_id=<%
35:              Response.Write tableSet("news_id")%>">
36:              <%= tableSet("news_id")%>
37:          </A>
38:      </TD>
39:<%      catSet.MoveFirst
40:      catSet.Find "cat_id = "&tableSet("news_cat_id")
41:%>      <TD>
42:              <%= catSet("cat_name")%>
43:      </TD>
44:
45:<%      for col = 2 to (p_numberofColumns-1)
46:%>          <TD>
47:              <%= tableSet.fields(col).Value %>
48:            </TD>
49:<%        next %>
50:        </TR>
51:<%        tableSet.MoveNext
52:    wend
53:    tableSet.Close
54:    set tableSet = Nothing
55:
56:    catSet.Close
57:    set catSet = Nothing
58:%>
59:
60:</TABLE>
61:<INPUT TYPE="submit" VALUE="Delete Checked Rows">
62:</form>
63:
64:<A HREF="edit_news_rec.asp">Create a New Record</A>
65:
66:</CENTER>
67:<%
68:    outpostDB.Close
69:    set outpostDB = Nothing
70:else
71:
72:    Response.Write "You do not have access to this page." 

73:
74:end if
75:%>
76:</BODY>
77:</HTML>

For the most part, we just replaced the words link and links with news, but also we've added a slight enhancement (see Figure 8.3). Part of the news item is it's category, so we'll need a way for our administrator to set that. But rather than expect our administrator to remember every category ID, we're pulling the name from the news_categories table and displaying that. Additionaly, because we're not changing anything in the database—we're just reading it—we're setting the RecordSets to use Read Only locking. In other words, they don't have to lock anything at all.

Now you see part of the advantage of being as generic as we can. If we'd specifically listed the columns in the links table, we'd have to rewrite this whole page! Let's move on to edit_news_action.asp (see Listing 8.13).

Figure 8.3. With just a few simple modifications to edit_links.asp, we can display our edit page for news.


Code Listing 8.13. edit_news_action.asp: Changing/adding news items
0: <%@ LANGUAGE="VBSCRIPT" %>
1: <%  Response.buffer = true  %>
2: <!--#include file="adovbs.inc"-->
3: <!--#include file="pagetop.txt"-->
4: <!--#include file="isadmin.inc"-->
5: <%
6: if isAdmin then
7:
8:     set outpostDB = Server.CreateObject("ADODB.Connection")
9:     outpostDB.Open "outpost"
10:
11:    set deleteSet = Server.CreateObject("ADODB.RecordSet")
12:    deleteSet.Open "select * from news order by news_id",
13:        outpostDB, adOpenDynamic, adLockPessimistic, adCmdText
14:    p_thisDelete = 1
15:    while not deleteSet.EOF
16:       if cint(deleteSet("news_id")) = _
17:          cint(Request.form("p_delete").item(p_thisDelete)) then
18:           deleteSet.Delete
19:           deleteSetUpdate
20:           if p_thisDelete < Request.form("p_delete").Count then
21:               p_thisDelete = p_thisDelete + 1
22:           end if
23:       end if
24:       deleteSet.MoveNext
25:    wend
26:    deleteSet.Close
27:  set deleteSet = Nothing
28:
29:  outpostDB.Close
30:  set outpostDB = Nothing
31:
32:  Response.Clear
33:  Response.Redirect "http://localhost/edit_news.asp"
34:else
35:
36:  Response.Write "You do not have access to this page."
37:
38:end if
39:%>
40:</BODY>
41:</HTML>

In this case, literally all we did was change link and links to news. Again, being generic definitely has its advantages.

Now let's move on to edit_news_rec.asp (see Listing 8.14), where we start to get into the big changes.

Code Listing 8.14. edit_news_rec.asp: Adding the file upload box
0: <%@ LANGUAGE="VBSCRIPT" %>
1: <!--#include file="adovbs.inc"-->
2: <!--#include file="pagetop.txt"-->
3: <!--#include file="isadmin.inc"-->
4: <%
5: if isAdmin then
6:
7:     set outpostDB = Server.CreateObject("ADODB.Connection")
8:     outpostDB.Open "outpost"
9:
10:     set newsSet = Server.CreateObject("ADODB.RecordSet")
11:     newsSet.Open "select * from news order by news_id desc",_
12:         outpostDB, adOpenStatic, adLockOptimistic, adCmdText
13:     newsSet.MoveFirst
14:     if newsSet.EOF then
15:         p_news_id = 1
16:     else
17:        p_news_id = newsSet("news_id") + 1
18:     end if
19:
20:     p_news_id_in = Request.querystring("p_news_id")
21:     if p_news_id_in <> "" then
22:       newsSet.Find "news_id = " & p_news_id_in
23:     end if
24:     if p_news_id_in = "" or newsSet.EOF then
25:         p_news_cat_id = "0"
26:         p_news_name = ""
27:         p_news_desc = ""
28:         p_news_url = ""
29:      else
30:          p_news_cat_id = newsSet("news_cat_id")
31:          p_news_headline = newsSet("news_headline")
32:          p_news_blurb = newsSet("news_blurb")
33:          p_news_url = newsSet("news_url")
34:          p_news_id = p_news_id_in
35:          p_existing = p_news_id_in
36:      end if
37:
38:      newsSet.Close
39:      set newsSet = Nothing
40: %>
41:      <CENTER>
42:      <FORM ACTION="edit_news_rec_action.asp"
43:               METHOD="post" enctype="multipart/form-data">
44:      <INPUT TYPE="hidden" NAME="p_existing" VALUE="<%=p_existing%>">
45:      <h2>Edit News</h2>
46:      <TABLE>
47:      <TR>
48:         <TD>News ID </TD>
49:         <TD>
50:            <INPUT TYPE="hidden" NAME="p_news_id"
51:                 VALUE="<%= p_news_id %>">
52:            <%= p_news_id %>
53:        </TD>
54:    </TR>
55:    <TR>
56:       <TD>Category </TD>
57:       <TD><select NAME="p_news_cat_id">
58: <%          set catSet = outpostDB.Execute("select * from "_

59:                               & "news_categories")
60:           while not catSet.EOF
61:               Response.Write "<option VALUE="&chr(34)&_
62:                                     catSet("cat_id")&chr(34)
63:               if cint(catSet("cat_id"))=cint(p_news_cat_id) then
64:                   Response.Write " SELECTED"
65:               end if
66:               Response.Write "> "& catSet("cat_name")
67:               catSet.MoveNext
68:            wend
69: %>          </select>
70:        </TD>
71:     </TR>
72:     <TR>
73:        <TD>News Headline</TD>
74:        <TD><INPUT TYPE="text" NAME="p_headline" SIZE="50"
75:                     VALUE="<%=p_news_headline%>">
76:    </TR>
77:    <TR>
78:       <TD>News
					Blurb</TD>
79:       <TD><INPUT TYPE="text" NAME="p_blurb" SIZE="50"
80:                    VALUE="<%=p_news_blurb%>" MAXLENGTH="255">
81:    </TR>
82:    <TR>
83:        <TD>News filename </TD>
84:        <TD><INPUT TYPE="text" NAME="p_url" SIZE="50"
85:                       VALUE="<%=p_news_url%>" MAXLENGTH="100">
86:    </TR>
87:    <TR>
88:        <TD>News File to Upload: </TD>
89:        <TD><INPUT TYPE="file" NAME="p_file"></TD>
90:    </TR>
91:
92:    </TABLE>
93:
94:    <INPUT TYPE="submit">
95:
96:    </form>
97:    </CENTER>
98: <%
99:    outpostDB.Close
100:   set outpostDB = Nothing
101:else
102:
103:    Response.Write "You do not have access to this page."
104:
105:end if
106:%>
107:</BODY>
108:</HTML>

In this case, we did hard-code the field names, so we'll have to change the names to match the news table. We also needed to add a field for the category ID, which didn't exist in the links table. We're doing all of that on lines 25 through 36.

On lines 56 through 71 we added a line to the form for our news category, checking to make sure that the current category for the item is marked as selected. Again, we didn't want to just display a category ID—or even worse, expect our administrator to type it in—so we're creating a pull-down menu.

The only thing new here is the way that we've implemented this. Normally, when we've been putting dynamic data into form elements, we've been doing it with the <%= %> syntax. This was because we wouldn't have to worry about how to print a double quote to the page. After all, if we tried

Response.Write ""Hello!""

ASP wouldn't know what to do with it. It would hit the second quote and think the line was finished, so it would consider everything from the "H" to the last quote an error. When we had single quotes in SQL, we could put two of them together and the database knew what to do with it. Not so for double quotes and VBScript.

Instead, what we did this time on line 62 was to use Response.Write, but for each double quote we've told ASP to print out character number 34. Every character you can type (and lots that you can't) has a number, called an ASCII code. It just so happens that the ASCII code for a double quote is 34. So if catSet(cat_id) was 5, the code

Response.Write "<option VALUE="&chr(34)&catSet("cat_id")&chr(34)&>

is going to print out

<option VALUE="5">

None of this has been too much of a change from editing the links table, but now we're getting into something new. On line 89, we've put in a new kind of form element, a file element. This tells the browser to display not only a box for the name of the file, but a Browse button that will let us designate a file to upload (see Figure 8.4).

Figure 8.4. The file element tells the browser to let us browse our computer for a file to upload.


But the file element won't do us any good unless the browser also knows it should send the whole file, and not just the name. We tell it to do so by adding an encoding type to the form tag on lines 42 and 43.

enctype="multipart/form-data"

is required if we're going to be uploading files.

Those were substantial changes, but they're nothing compared to what we're going to do with edit_news_rec_action.asp. That's where we're actually going to take in that file and do something with it. Open edit_news_rec_action.asp and add the changes in Listing 8.15.

Note

If you didn't register and install the ASPUpload component back in Chapter 6, "Adding Person-To-Person Auction Capabilities," go back and do it now.


Code Listing 8.15. edit_news_rec_action.asp: Saving the uploaded file
0: <%@ LANGUAGE="VBSCRIPT" %>
1: <%  Response.buffer = true   %>
2: <!--#include file="adovbs.inc"-->
3: <!--#include file="pagetop.txt"-->
4: <!--#include file="isadmin.inc"-->
5: <%
6: if isAdmin then
7:
8:     set Upload = Server.CreateObject("PersitsUpload.1")
9:     count = Upload.Save("c:inetpubwwwroot")
10:
11:    p_news_id = cint(Upload.form("p_news_id"))
12:    p_news_cat_id = cint(Upload.form("p_news_cat_id"))
13:    p_news_headline = cstr(Upload.form("p_headline"))
14:    p_news_blurb = cstr(Upload.form("p_blurb"))
15:    p_news_url = cstr(Upload.form("p_url"))
16:    p_existing = cstr(Upload.form("p_existing"))
17:
18:    set Upload = Nothing
19:
20:    set outpostDB = Server.CreateObject("ADODB.Connection")
21:    outpostDB.Open "outpost"
22:
23:    set insertSet = Server.CreateObject("ADODB.RecordSet")
24:    insertSet.Open "news", outpostdb, adOpenDynamic, _
25:        adLockOptimistic, adCmdTable
26:
27:    if p_existing = "" then
28:      insertSet.AddNew
29:    else
30:        insertSet.Find "news_id =" & p_existing
31:    end if
32:    insertSet("news_id") = p_news_id
33:    insertSet("news_cat_id") = p_news_cat_id
34:    insertSet("news_headline") = p_news_headline
35:    insertSet("news_blurb") = p_news_blurb
36:    insertSet("news_url") = p_news_url
37:    insertSetUpdate
38:    insertSet.Close
39:    set insertSet = Nothing
40:
41:    outpostDB.Close
42:    set outpostDB = Nothing
43:
44:    Response.Clear
45:    Response.Redirect "http://localhost/edit_news.asp"
46:else
47:
48:    Response.Write "You do not have access to this page."
49:
50:end if
51:%>
52:</BODY>
53:</HTML>

Except for changing the names and accommodating the news_cat_id field, we really only added three lines to this page, but they make all the difference in the world.

On line 8, we're creating an instance of the Upload object, the third-party component that will handle the information we've told the browser to send. Line 9 is where we're actually doing the work, asking it to Save. Until we do that, we won't be able to get at any of the information, including the file.

When we tell the Upload object to Save, it looks through all of the content and headers that were sent to the server and picks out the files and the rest of the form data. We could even, if we wanted, send multiple files at one time by creating more than one file element to our form. The Upload object will then save them in whatever directory we've specified on line 9.

It would seem that that was all we had to do, but that's not quite true. Because of the encoding we used—multipart-formdata—the rest of our form elements aren't available to the normal Request.form object. Fortunately, the Upload object takes care of that, basically replacing Request.form with Upload.form, so we can still get at our data.

Finally, on line 18, we destroy the Upload object. We've saved the data from it, so we can destroy it and and save our data to the database as usual.

Here's a question, though: If Upload saves the file with it's original name (which it will) and also enables us to retrieve that name (which it does, using Upload.files().path), why did we bother to include a field for our administrator to enter a filename? Wouldn't it just make more sense for them to upload it directly to it's final location and be done with it?

The answer is a definite sometimes. If we were to go that route, the file would have to be completely prepared, including headers and footers, before it was uploaded. There's nothing wrong with that if we have a low volume of material and an administrator with time to spare. Of course, we'd never be able to use that file in any other way, say, as a compilation of some sort.

But what if we could upload a plain text file and have the server do the rest of the work for us? That's what we'll talk about next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.242.128