Application.Download(path, name) result in redirected to download.wx and 404 error.

Welcome to Wisej Support.
Questions, suggestions and plain old bugs - are all welcome here!
Answered
0
0

Hi,

 

As title, when I try the method: Application.Download(string filePath, string fileName) to download a PDF to client, it return an 404 error with the browser being redirected to “download.wx?x=……” page.

I am not sure if it is a bug, or I have made something wrong with it. I am sure the file being download is exist in server as I try the component PDF Viewer it work very well.

 

Regards,

Felix

  • You must to post comments
Best Answer
2
0

Hi Thomas,

 

Thanks for your sample code.

By implementing the IWisejHandler.ProcessRequest(HttpContext context) I am managed to create a file download solution I need:

— File storage is not under the web app folder,

— use HttpRespone.OutputStream, and

— create the Zip on the fly without create any temp file.

I modified the sample code a little bit to remove the use of a MemoryStream (as the size of my zip file can be as big as 500Mb), as below:

  void IWisejHandler.ProcessRequest(HttpContext context)
  {
   //// create a ZIP file in memory
   //var memStream = new MemoryStream();
   //using (var zip = new ZipArchive(memStream, ZipArchiveMode.Create, true))
   //{
   //    zip.CreateEntryFromFile(Path.Combine(Application.StartupPath, "Wisej-Datasheet-V2.2.pdf"), "TestFile.pdf", CompressionLevel.Fastest);
   //}

   //// reset the position in the stream
   //memStream.Position = 0;

   // now that we have the ZIP, handle the request individually
   var response = context.Response;
   response.AddHeader("Content-Type", "application/zip");
   response.AppendHeader("Content-Disposition",
    new ContentDisposition()
    {
     // provide a filename to use
     FileName = "test.zip",
     // DispositionType can be "inline" or "attachment"
     DispositionType = "inline"
    }.ToString());

   //// now copy the stream with our ZIP file to the response output
   //memStream.CopyTo(response.OutputStream);

   using (PositionWrapperStream outputStream = new PositionWrapperStream(response.OutputStream))
   {
    using (var zip = new ZipArchive(outputStream, ZipArchiveMode.Create, true))
    {
     zip.CreateEntryFromFile(Path.Combine(Application.StartupPath, "Wisej-Datasheet-V2.2.pdf"), "TestFile.pdf", CompressionLevel.Fastest);
    }
   }
 }

Regards,

Felix CHAN

  • Thomas (ITG)
    Great, I am glad it worked out for you.
  • You must to post comments
2
0

Hi Felix,

I put together a small sample that illustrates the different options for providing downloads with Wisej. It also shows how to build a ZIP file in memory and send back the stream to the browser without having to save to disk. Basically an example of how to to use the powerful IWisejHandler interface.

Hope this helps!

Best wishes
Thomas

Attachment
  • You must to post comments
0
0

Hi Luca,

Thanks for your explanation. I fully understand what is the reason behind.

For Download stream, as below:

Wisej saves the entire stream content to a temporary file, then when processing the download callback gives the temp path to the web server and deletes the temp file.

I am concerning is there any performance issue when I need to implement a DownloadAsZipStream(List<FileInfo> listOfFilesToBeIncludedInTheZipStream), which allow me to create a zip file on the fly. My ERP allows users to select multiple files (or select all) from a ListView control and then download them as one zip file. Currently my implementation (not WiseJ) will not create the zip file on the hard disk. Instead, I open a output stream on the HttpResponse (is a ZipStream) and add those selected files to it one by one on the fly.

If the total size of all files in the List<FileInfo> is large, let say over 200 JPGs and size is around 500Mb, or more, WiseJ internally will copy my ZipStream to a temp file ?

Or I have to create the zip file and place it under a folder under the web app and call Application.Download(filePath)? Also, when I have to delete that zip file ?

Regards,

Felix CHAN

 

  • You must to post comments
0
0

Hi Felix,

No worries about the English. We are all from all over the world here. 🙂

You are correct that we could do that, but there is a difference internally in the implementation of Download file and Download stream. When you use Download file, wisej simply generated the download url callback, then when processing the callback passes the path of the original file to the web server and lets the server handle it.

When you use Download stream, Wisej saves the entire stream content to a temporary file, then when processing the download callback gives the temp path to the web server and deletes the temp file. So using Download file eliminates one step.

Best,

Luca

  • You must to post comments
0
0

Hi Luca,

First of all, sorry for my poor English as it is not my native language. I think I have ask the question in a wrong direction. Maybe let me rephrase my question below. The file download problem is solved (and thanks Frank). I am just ask something I am interested in.

The method Application.Download(string localFilePath, string name) does not support downloading file outside the web app folder to the client from the server. But the method Application.Download(Stream stream, string name) allow and work very well.

Why not WiseJ implement the Application.Download(string localFilePath, string name) look like this:

using System.IO;

public static void TheNewDownloadMethod(string localFilePath, string name = null)
{
   //try
   //{

       /// Need to check for null value of localFilePath, etc...

       FileInfo fiDownload = new FileInfo(localFilePath);

       /// Need to check for file exists, is local file, is allow to read, etc...

       if (name == null)
       {
           name = fiDownload.Name;
       }
       using (FileStream fileStream = fiDownload.OpenRead())
       {
           Application.Download(fileStream, name);
       }
   //}
   //catch (Exception ex)
   //{
   //    log.Error("Error in downloading file.", ex);
   //}
}

Hope this will make the question more clear.

I just wondering if this is correct or not, and should I (and every developers) need to do in this way when the program need to download a file by a file path (string).

 

Regards,

Felix CHAN

  • You must to post comments
0
0

Hi Felix,

The reason is that the URL used to download the file can be modified to access other files outside of the app. It’s not easy but it’s possible. That why also other web frameworks don’t let a URL download anything outside of the application.

See this post: https://wisej.com/support/question/directory-traversal-security-issue

Best,

Luca

  • You must to post comments
0
0

Hi Frank,

Thanks. It works when I change the code and pass a Stream into it instead of a filePath.

However, what I am using is just a local file path, such as “D:\DocBase\SomeTestingFile.pdf”. It is located in the same machine of the web server. There is nothing related to external URLs.

Secondly, PDF Viewer works because its “path is directly provided by my application…”, but for this Download() operation, the filePath is also provided by my application.

I don’t understand the concern and reason behind. But in all, what I need to do is to code a block of code instead of one single line, as below.

//Application.Download(fiDownload.FullName, displayName);
try
{
    if (displayName == null)
    {
        displayName = fiDownload.Name;
    }
    using (FileStream fileStream = fiDownload.OpenRead())
    {
           Application.Download(fileStream, displayName);
    }
}
catch (Exception ex)
{
     log.Error("Error in downloading file.", ex);
}

Anyway, Thanks for the solution. I will continue to try converting an ERP from WVG into WiseJ.

Regards,
Felix CHAN

  • You must to post comments
0
0

Hi Felix,

what you are observing is intended behavior.
Due to security reasons the Download function is restricted to the applications project directory to avoid spoofing of external URLs.

It works with the PDF viewer as its path is directly provided by your application.

If you need to make it work with a file outside your project directory you need to use a stream for it.

Hope that helps.

Best regards
Frank

  • You must to post comments
Showing 8 results
Your Answer

Please first to submit.