Q&A
Transfer Files Over the Internet
Use FTP or HTTP POST to transfer files over the Internet with .NET. Also learn how to secure a database Connection string.
Technology Toolbox: VB.NET, C#, SQL Server 2000, ASP.NET
Q:
How do I transfer files to a remote server over the Internet using .NET?
A:
There are two standard ways to transmit files over the Internet. The first is to use the HTTP POST verb to transmit files (or just plain data) to a receptor, which then saves them on the remote server. The second is to use File Transfer Protocol (FTP) to connect to a remote server, then transmit the files directly to the remote FTP server, which saves them on the remote server.
HTTP posting requires two pieces. The first piece is the program that recognizes HTTP POST requests (an acceptor), gets the filenames and file data from the request, and saves them in the desired location. The second piece includes the file data's sender and the desired filename (a poster).
I'll walk you through a sample project that shows you how to do this, studying the acceptor first. Name the acceptor Uploader.aspx, and use the Page_Load event to house all your code (see Listing 1). All the acceptor does is look for the filename sent from the requestor, get the file data, and save the data to a specified location on the local server. This Web page includes a single label populated with the status of the save. The poster can query the HTML within the page and look for this label to determine the status of the operation. You could easily modify the acceptor so it saves the data to another location or saves the data dynamically based on some other data posted by the requestor. Finally, compile the project and deploy it to an ASP.NET Web server.
You need to build a poster after you deploy the acceptor. This sample poster is a small VB.NET Windows Forms app that posts the data. The poster can be either a Web page or a rich desktop client. The sample WinForms app provides textboxes for the user to enter a local filename to upload and the name of the acceptor (Uploader.aspx, in this case).
Once the proper entries are made, you use the WebClient class to establish a connection to the specified acceptor. Next, use the UploadFile method to take a file on the local machine and post it to the acceptor:
myWebClient = New WebClient
httpResponseArray = _
myWebClient.UploadFile( _
uriString, "POST", _
LocalFileName)
The UploadFile method passes back a byte array, the string of HTML returned by the Uploader.aspx file. This lets you look for the label you output as part of the acceptor so you can determine the status of the save.
Sending a file using the HTTP POST method is easy. Simply open up a WebClient connection to the desired target and use the UploadFile method to send a file using the HTTP POST command. The uriString is the complete URI to the acceptor that you deployed (for example: http://www.myserver.com/TestUploader/Uploader.aspx). Note that you must specify the complete URI and the filename. The UploadFile method won't work if you use only the directory and set Uploader.aspx to be the default page for that directory. The page name must be part of the URI passed to UploadFile.
The WebClient class also includes an UploadData method to upload raw data to a remote Web server using HTTP POST. The drawback to this method is that you must provide both ends of the client.
The second way to transfer files over the Internet is to use FTP. The beauty of using FTP is that the acceptor is ready already and it's platform-agnostic. All you have to do is create some requestor code to communicate using FTP.
You can use one of two approaches to communicate using FTP. The easiest way is to use the unmanaged code within WININET.dll (a core Windows system DLL), which does the bulk of the work for you. For example, assume you want to import references to specific functions that you want to use within the WININET.dll (see Listing 2). After you build the FTP class, it's a simple matter to consume the methods in WININET.dll to send a file to a remote FTP server (see Listing 3).
A second approach to implementing FTP is to roll your own FTP class by overriding the WebRequest and WebResponse classes of the System.Net namespace. You can then include the functionality of the specific FTP commands yourself (see Additional Resources).
Q:
How can I secure my application's database connection string and prevent others from getting unauthorized access to my database?
A:
You have a handful of options if you want to secure your database connection string from prying eyes, but most boil down to one of two choices: obfuscation (hiding) or encryption. Encryption can affect your application's performance negatively, so you need to decide who you're securing your connection string from and why before you choose that option.
For example, assume you're a small shop with a single developer who manages the servers and databases. In this case, a single level of obfuscation will probably suit your needs best. If you're deploying a Windows client desktop application, you might want to consider storing the connection string (encrypted or not) in a centralized location, accessible only to the application. If you're implementing your application on a server farm residing at an application service provider's server farm, you might want to implement encryption to prevent unauthorized access to your database.
Hiding the connection string means storing it in a location separate from where you use it in the code. However, be aware that anyone can use ILDASM on your ASP.NET or Windows client application. This means they can debug your application and try to get the database connection string by looking for constants in the code that fit the connection string format.
Popular places to hide a database connection string include the Web.Config file, the Registry, a database, or a remote location accessible only through a Web service or remoting call. You can use the System.Security.Cryptography namespace to add encryption to any of the strategies just mentioned to yield another level of security to your connection string.
However, the safest way to secure your database connection string is to never expose it to the application in the first place. You can do this by developing an assembly that contains a class whose sole responsibility is to return a database connection (and not the connection string) to the caller. The assembly can live in the Global Assembly Cache (GAC) and can use the instantiator's assembly ID as a key to make sure it's on the list of approved assemblies that can have a database connection. You can use this approach to ensure you never send any database credentials back and forth to be intercepted and decrypted. Someone using ILDASM on your application will see only the database connection object, not the credentials used to create that connection.
Creating a database connection class is simple (see Listing 4). After creating the class, deploy it to the GAC, add a reference in your application, and use the class exactly as you would use the SqlConnection class. Deploying an assembly to the GAC for a Windows-based client is simple because you can make it part of the app's installation and you can auto-update new versions. This code consumes the Get method from your DBConnection class in the example:
myDBConnection SqlConnection =
new MyConnectionString.DBConnection();
You could pass parameters to the Get method easily if you want to have some other criteria for validating access to the method. The important thing to remember is that using this method doesn't expose your database connection string (or your connection credentials) across the wire.
About the Author
Doug Thews is the director of software development for D&D Consulting Services in Dallas. Doug has more than 19 years of software-development experience in C/C++, VB/ASP, and VB.NET/C#. He writes the Getting Started column for Visual Studio Magazine, and coauthored the book, Professional ASP.NET Performance (Wrox/Wiley Press). Reach Doug at [email protected].