• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 964
  • Last Modified:

How to download a file thru Ftp using Asp.Net/Visual Basic (visual studio 2008)

I give access to a multimedia module to clients that paid a 5 day subscription. This is part is working.
I am using an external hosting so my server does not slow down/saturate. I am using ftp with username and password, but I am using an asp link button (to hide link) wich uses response.redirect(directlink). But need to change this for 2 reasons.

1


Security... a curious client can somehow check the link and give it to any other client (they have to pay for access).

2


Internet Explorer (i'm using ver 8) does not allow clients to download with username and password directly (for reason 1)
...and, fo course, i can not tell them to use my preferred browser, they will probably stick with Internet Explorer.

I have tried several examples found over the internet, and have googled-it enough times, no luck.

Mostly using streamwriter and streamreader, but the examples need a location to download, and i would like the client to click, get the Save dialog, you know, the usual easy download... in other words, let the client's operating system take care of download location, not my app; my app will make the connection to the server, check if there's a file (haven't done this either) and start download if it does.
0
jmnf
Asked:
jmnf
  • 6
  • 3
  • 2
  • +1
1 Solution
 
SunnyDarkCommented:
I could suggest the following:
Client clicks a link something like : downloadfile.aspx?fileid=11111

The Page_Load event of downloadfile.aspx then checks the clients credentials and if it's a registered client reads the file from the disk and sends it to the Response stream.
I havent touched VB for a while so I'll just pseudo code, should be hard to translate
public Page_Load(e)
{
  if (Page.User.IsRegistered) 
  then
  {
     FileStream readin = File.Open(GetFileLocation[Request[fileid]))
     ArrayOfBytes data[4096]
     while ( not readin.EndOfFile)
     {
         int readbytes = readin.Read(data)
         Response.OutputStream.Write(data)
     }
     Response.Flush()
     Response.End()
  }
}

Open in new window

0
 
KetGuruCommented:
note manage the value of strFilelocation, strFileName, strContenttype

Private void FileLoad()
{
          if(UserAuthenticated)
          {
               FileStream fs = File.Open(strFilelocation)

              Response.Clear();
              Response.Buffer = true;
             Response.ContentType = strContentType;
             Response.AddHeader("content-disposition", "attachment; filename=" + strFileName);
             byte[] filedata;
              int temp = fs.Read(filedata)
            Response.BinaryWrite(FileData);
            Response.End();

        }
}
0
 
jmnfAuthor Commented:
SunnyDark and KetGuru

I believe i have tried both of this solutions before, i will try them again and report back... the problem with this 2 solutions is that my file is on an external ftp server, and also, it requires credentials. On the other hand, 1 of my files is 2.3 GB and 8 files of around 500 MB.

I know how to download from webapp server using response.transmitfile for sending very large files, but the external ftp server and the use of credentials (hidden credentials) is another problem.

I'll report back.
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
KetGuruCommented:
It is too big file. asp.net is not recommended option in this case than. I would suggest to use some batch file with ftp command and call/run that file from asp.net if you are keen to execute from asp.net only.
0
 
SunnyDarkCommented:
Also don't forget to pay attention to Server.ScriptTimeout property to allow the needed time to download and stream the file.
0
 
jmnfAuthor Commented:
I have been using the following procedure in the past to download a DVD image (.ISO) of 2.3 GB size and it works with

<httpRuntime executionTimeout="21600"/>

The only problem is that I had to remove the files from my onw server and now they are in a remote server, and I download them thru ftp (direct link), because the downloads were eating our bandwidth.

    Private Sub largeFileDownload(ByVal largeFile As String)
        Dim path As String = Server.MapPath(largeFile)
        Dim file As System.IO.FileInfo = New System.IO.FileInfo(path)

        If file.Exists Then
            Response.Clear()
            Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name)
            Response.AddHeader("Content-Length", file.Length.ToString())
            Response.ContentType = "application/octet-stream"
            Response.TransmitFile(file.FullName)
            Response.End()
        End If

    End Sub

Open in new window


So you see it is possible, but I need to have the ability to download them with network credentials (from the remote server) and that way avoid using a direct link.
0
 
jmnfAuthor Commented:
Thanks for the time and effort you are putting into this
0
 
jmnfAuthor Commented:
Forgot to tell you...

i am currently downloading them with the current code inside a link button click:

dim sFullURL as string = "ftp://username:password@remoteserver.com/filename.iso"
response.redirect(sFullURL)

Open in new window


but like i said on the original post, Internet Explorer won't let me download like this... and in firefox and some other browsers, if there is any error, it will show a page with the actual link, showing username and password.
0
 
CodeCruiserCommented:
If you would download the file to your server first and then stream it to the user then its no use keeping the file on a separate server. It would double you bandwidth usage instead.

Do you have the ability to generate temporary username passwords?
0
 
jmnfAuthor Commented:
I do not stream those files thru my web server, they get downloaded directly; i would have noticed the lag on my server.

I can't create temporary usernames and passwords because the ftp server is in a hosting service (wich i administer thru cPanel), i can create manually those usernames and passwords, so creating credentials for each client on my server is possible, but I would have to create 20 or 30 username and passwords daily on the remote FTP server (in the hosting service) for the sole purpose of letting the clients download with their temporary credentials.

When testing some procedures wich require a path on the client computer to save the file, I receive an Access Denied error, wich I believe is caused by the procedure trying to "write" the file on the server, instead of doing it on the computer I'm testing it on. I believe, then, that the connection to the FTP server is being made correctly, but I can't seem to figure out the problem of saving the file. I'm stuck... I have been looking and looking and looking with no luck... last time I tried a procedure with WebClient instead of FtpWebRequest / FtpWebResponse.

Help anyone, please. Some other ideas too, thanks.
0
 
SunnyDarkCommented:
The problem is as follows:
Whenever you use WebClient or any of the xxxWebRequests you ARE streaming content through your server, since the content gets downloaded to your server first and then streamed to the client computer. I believe that is not what you want, otherwise you would just store the files on your webserver.
So what yo want is to use response.redirect, however that will disclose the real URL including password and username to the client , since the file will be downloaded directly by the client's browser so the browser will have to know the actual URL of the FTP. So the conclusion is, you will not be able to do what you want the way you are trying to with external FTP. I would suggest using some other alternative service to host the files, one that will allow you to create temporary expiring links. One such service is Amazon S3: http://aws.amazon.com/s3/
The .NET API is very simple and allows you to create temporary signed URLs with expiration date in one simple call:
AmazonS3Client s3 = new Amazon.S3.AmazonS3Client(awskey,awssecret);
string url = s3.GetPreSignedURL(new GetPreSignedUrlRequest
{
   BucketName = "the name of the folder",
   Key = "the name of the file",
   Expires = new DateTime(2011, 6, 12)
});
Response.Redirect(url);

Open in new window

0
 
jmnfAuthor Commented:
Thank you for your effort, I am currently looking for workarounds, as there is no easy solution as you explained.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 6
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now