ASP.NET/VB.NET web application.
Currently I'm creating a Word document and streaming it to the user. The browser handles this great with an "open/save" dialog, etc...
Basically the webform has a multi-select listbox. They select one or MORE documents and click the "Generate/Download" button. Works great for a single file. But multiple files doesn't work. Here's part of my code....
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.AddHeader("Content-Disposition", Convert.ToString("attachment; filename=") & DocFileNameDestination)
HttpContext.Current.Response.AddHeader("content-length", finalDocumentStream.ToArray().Length.ToString())
HttpContext.Current.Response.ContentType = "application/ms-word"
HttpContext.Current.Response.BinaryWrite(finalDocumentStream.ToArray())
HttpContext.Current.Response.Flush()
HttpContext.Current.ApplicationInstance.CompleteRequest()
Question: How can I allow the user to download all selected files at one time. I would prefer a really simple solution. (Even if I have to create a zip... only if easier.)
Thanks in advance!
You can download them one at a time in a loop. If you want to download them all at once, you can download each one in a separate thread by starting a backgroundworker for each file in the loop.
Related
A bit of an odd use-case scenario but I have the need for a program
that allows users to select file(s) and have those full path file
names sent to a SQL database.
I’ve built said program in ASP .NET Web application written in VB
using Visual Studio 17.3.5. The FileUpload Control records the users
selected files and those filenames successfully transfer to the SQL
database.
The problem I’m having is it appears the FileUpload control is doing
what’s it’s designed to do… actually upload the file, not sure where
but I’m assuming to some temp space. I noticed this when I selected
a large file to test with, there was a lag in the system and if the
file was larger than ‘maxRequestLength’ it would crash. Again my goal
is to record and save just the filenames of the selected files not the
actual files themselves.
If it wasn’t obvious I’m very green when it comes to coding, any help
is greatly appreciated!
Initially I increased 'maxRequestLength' in the Web.config but that
didn't address the problem, which is the FileUpload control is
actually uploading or trying to upload the file somewhere.
Current code related to FUD:
*Side note: I’m using a Wizard control and this code is submitted/executed when the user clicks ‘Finish’ at the end of the Wizard.
If fud_SelectFiles.HasFiles Then
For Each uploadedfile In fud_SelectFiles.PostedFiles
StrFile_Name += String.Format(Server.MapPath(uploadedfile.FileName)) + ","
'Trims last comma from file name and places into session variable
Session("v_File_Name") = StrFile_Name.TrimEnd(",")
Next
End If
Error message:
The process cannot access the file 'C:\SampleProjectName\mytestcsv.csv' because it is being used by another process.
I am trying to read numerous files (CSV, XML, HTML) in asp/VB.net using the fileupload (file upload) control.
I'm saving the file using Server.MapPath so I can process the file in another procedure. It's very odd, but sometimes I can browse and upload the same file over and over with no issues, but sometimes it immediately fails.
I've found that I can ultimately kill the WebDev.WebServer40.exe it releases whatever lock is present. This is annoying, but fine for my debugging... but unacceptable for endusers.
My fileupload code:
If fuImport.HasFile Then
If (System.IO.File.Exists(Server.MapPath("myhtml.html"))) Then
System.IO.File.Delete(Server.MapPath("myhtml.html"))
End If
Dim dtFromHTML As New Data.DataTable
Dim dtFromSQL As New Data.DataTable
Try
fuImport.SaveAs(Server.MapPath("mytestcsv.csv"))
'Process data here
ProcessCSVData(Server.MapPath("mytestcsv.csv"))
Catch ex As Exception
Response.Write("error: " & ex.Message)
Finally
fuImport.PostedFile.InputStream.Flush()
fuImport.PostedFile.InputStream.Close()
fuImport.FileContent.Dispose()
End Try
'Other things happen here
Else
Response.Write("no file...")
End If
Any ideas would be appreciated.
Use FileShare.Read to read a file even if it is opened exclusively by an another process.
You may not be releasing the file in your code for access. You should use the keyword "using".
Read this post:
The process cannot access the file because it is being used by another process - using static class
and this:
http://msdn.microsoft.com/en-us/library/htd05whh.aspx
I am not a VB.NET coder but try something along the lines of:
Using {fuImport.SaveAs(Server.MapPath("mytestcsv.csv")) }
ProcessCSVData(Server.MapPath("mytestcsv.csv"))
End Using
The next procedure that uses file...
Try closing input stream before accessing the file:
UPDATED To use temp filename
Dim sTempName = Path.GetRandomFileName
fuImport.SaveAs(Server.MapPath(sTempName))
'close before accessing saved file
fuImport.PostedFile.InputStream.Close()
'Process data here
ProcessCSVData(Server.MapPath(sTempName)
I am currently working with ASP.NET MVC and I have an action method that displays few reports in the view in table format.
I have a requirement to export the same table to an Excel document at the click of a button in the View.
How can this be achieved? How would you create your Action method for this?
In your controller action you could add this:
Response.AddHeader("Content-Disposition", "filename=thefilename.xls");
Response.ContentType = "application/vnd.ms-excel";
Then just send the user to the same view. That should work.
I'm using component, called Aspose.Cells (http://www.aspose.com/categories/.net-components/aspose.cells-for-.net/).
It's not free, though the most powerful solution I've tried +)
Also, for free solutions, see: Create Excel (.XLS and .XLSX) file from C#
Get data from database using your data access methods in dot net.
Use a loop to get each record.
Now add each record in a variable one by one like this.
Name,Email,Phone,Country
John,john#john.com,+12345,USA
Ali,ali#ali.com,+54321,UAE
Naveed,naveed#naveed.com,+09876,Pakistan
use 'new line' code at the end of each row (For example '\n')
Now write above data into a file with extension .csv (example data.csv)
Now open that file in EXCEL
:)
I was wondering what's the best practise for serving a generated big file in classic asp.
We have an application with "export to excel" function that produces 10MB files. The excels are created by just calling a .asp page that has the Response.ContentType set to excel and has an HTML table for the data.
This gives as problem that it takes 4 minutes before the user sees the "Save as..." dialog.
My current solution is to call an .asp page that creates the excel on the server with AJAX and lets the page return the URL of the generated document. Then I can use javascript to display the on the original page.
Is this easy to do with classic asp (creating files on server with some kind of stream) while keeping security in mind? (URL should make people be able to guess the location of other files)
How would I go about handling deleted the generated files overtime? They have to be deleted periodicly as the data changes in realtime.
Thanks.
edit: I realized now that creating the file on the server will probably also take 4 minutes...
I think you are selecting a complex route, when the solution is simple enough (Though I may be missing some requirements)
If you to generate an excel, just call an asp page that do the following:
Response.clear
Response.AddHeader "content-disposition", "attachment; filename=myexcel.xls"
Response.ContentType = "application/excel"
'//write the content of the file
Response.write "...."
Response.end
This will a start a download process in the browser without needing to generate a extra call, javascript or anything
See this question for more info on the format you will choose to generate the excel.
Edit
Since Thomas update the question and the real problem is that the file take 4 minutes to generate, the solution could be:
Offer the user the send the file by email (if this is a workable solution in you server or hosting).
Generate the file async, and let the user know when the file generation is done (with an ajax call, like SO does when other user have added an answer)
To generate the file on the server
'//You should change for a random name or something that makes sense
FileName = "C:\temp\myexcel.xls"
FileNumber = FreeFile
Open FileName For Append As #FileNumber
'//generate the content
TheRow = "...."
Print #FileNumber, TheRow
Close #FileNumber
To delete the temp files generated
I use Empty Temp Folders a freeware app that I run daily on the server to take care of temp files generated. (Again, it depends on you server or hosting)
About security
Generate the files using random numbers or GUIds for a light protection. If the data is sensitive, you will need to download the file from a ASP page, but I think that you will be in the same problem again...(waiting 4 minutes to download)
Read file using FSO.
Set headers for Excel file-type, name according to file read and for download (attachment)
Flush response after headers are set. The client should display "save as" dialogue.
Output FSO to response. Client will download file and see progress bar.
How do you plan to generate the Excel? I hope you don't plan to call Excel to do that, as it is unsupported, and generally won't work well.
You should check to see if there are COM components to generate Excel that you can call from Classic ASP. Alternatively, add one ASP.NET page for the purpose. I know for a fact that there are compoonents that can be called from ASP.NET pages to do this. Worse come to worst, there's an Excel exporter component from Infragistics that works with their UltraWebGrid control to export. The grid need not be visible in order to accomplish this, but styles in the grid translate to styles in the spreadsheet. They also allow you to manipulate the spreadsheet programmatically.
How can I export the data in my webapp to an Excel sheet from ASP.NET (VB.NET,SQL 2005)?
change the contenttype of your ASP.Net page
Response.ContentType = "application/ms-excel"
One of my most popular blogs is how to generate an Excel document from .NET code, using the Excel XML markup (this is not OpenXML, it's standard Excel XML) - http://www.aaron-powell.com/linq-to-xml-to-excel
I also link off to an easier way to do it with VB 9.
Although this is .NET 3.5 code it could easily be done in .NET 2.0 using XmlDocument and creating the nodes that way.
Then it's just a matter to set the right response headers and streaming back in the response.
SpreadsheetGear for .NET will do it. You can find a bunch of live ASP.NET samples with C# & VB.NET source on this page.
Disclaimer: I own SpreadsheetGear LLC
If you can display your data in a GridView control, it inherently supports "right-click-->Export to Excel" without having to write any code whatsoever.
SQL Server Reporting services would be the best way to export data from an application into Excel.
If you dont have access to / dont wan't to use reporting services depending on the data you want to extract / format possibly using a CSV structure instead of Excel may be easiest.
Use the Microsoft.Office.Interop.Excel dlls to create excel files with your data and then provide links to download the files using Hunter Daley's download method...
As a general solution, you may want to consider writing handler (ashx) for exporting -- and pass either the query parameters to recreate the query to generate the data or an identifier to get the data from the cache (if cached). Depending on whether CSV is sufficient for your Excel export you could just format the data and send it back, setting the ContentType as #Hunter suggests or use the primary interop assemblies (which would require Excel on the server) to construct a real Excel spreadsheet and serialize it to the response stream.
I prefer to use a OLEDB connection string.
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Excel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1";
Not sure about exporting a page but if you just want to export a dataset or datatable
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))
HttpContext.Current.Response.ContentType = "application/ms-excel"
Dim sw As StringWriter = New StringWriter
Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
Dim table As Table = New Table
table.RenderControl(htw)
' render the htmlwriter into the response
HttpContext.Current.Response.Write(sw.ToString)
HttpContext.Current.Response.End()
I use almost the same exact code as CodeKiwi. I would use that if you have a DataTable and want to stream it to the client browser.
If you want a file, you could also do a simple loop through each row/column, create a CSV file and I guess provide a link to the client - you can use a file extension of CSV or XLS. Or if you stream the resulting file to the client it will prompt them if they want to open or save it to disk.
The interops are (well were last time I tried them) great for small datasets, but didn't scale well - horrifically slow for larger datasets.