Save File Prompt instead of FileWriteAllBytes - asp.net

Long time lurker first time poster. Working with .Net / Linq for just a few years so I'm sure I'm missing something here. After countless hours of research I need help.
I based my code on a suggestion from https:http://damieng.com/blog/2010/01/11/linq-to-sql-tips-and-tricks-3
The following code currently saves a chosen file (pdf, doc, png, etc) which is stored in an sql database to the C:\temp. Works great. I want to take it one step further. Instead of saving it automatically to the c:\temp can I have the browser prompt so they can save it to their desired location.
{
var getFile = new myDataClass();
//retrieve attachment id from selected row
int attachmentId = Convert.ToInt32((this.gvAttachments.SelectedRow.Cells[1].Text));
//retrieve attachment information from dataclass (sql attachment table)
var results = from file in getFile.AttachmentsContents
where file.Attachment_Id == attachmentId
select file;
string writePath = #"c:\temp";
var myFile = results.First();
File.WriteAllBytes(Path.Combine(writePath, myFile.attach_Name), myFile.attach_Data.ToArray());
}
So instead of using File.WriteAllBytes can I instead take the data returned from my linq Query (myFile) and pass it into something that would prompt for the user to save the file instead?). Can this returned object be used with response.transmitfile? Thanks so much.

Just use the BinaryWrite(myFile.attach_Data.ToArray()) method to send the data since it is already in memory.
But first set headers appropriately, for example:
"Content-Disposition", "attachment; filename="+myFile.attach_Name
"Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
Content-type guides the receiving system on how it should handle the file. Here are more MS Office content types. If they are known at the point the data is stored, the content-type should be stored, too.
Also, since the file content is the only data you want in the response, call Clear before and End after BinaryWrite.

Related

FileResult not returning proper file type and file name

I have an ASP.NET MVC application with an ActionResult called GenerateReport. I'm trying to return a byte array to save an Excel file. Here are snippets:
var contentType = "application/vnd.ms-excel";
var fileName = "Statistics.xlsx";
...
var fileBytes = package.GetAsByteArray();
return File(fileBytes, contentType, fileName);
When I'm prompted to save the file, it sometimes (but not always) asks what I want to do with "GenerateReport". It's naming the file the same as the ActionResult and it's not giving it a file type. I will request to save it and it will say that it failed to save. I will select Retry and it will save fine. Then, if I rename it to an .xlsx, all of the data is there and correct. I'm using IE9 and Chrome and I haven't noticed it happen in Chrome. Unfortunately, it needs to work in IE9.
Does anyone know why it's not getting my content type and file name sometimes?
Check the response for Content-Encoding. It might be the same issue like here PHP File Serving Script: Unreliable Downloads?

Upload File with FileUpload and Stock in database using Framwork entity

I want to upload file with file upload and stock in DataBase SQLserver using framework entity , I use this code :
string strRealPath = Request.PhysicalApplicationPath;
if(FileUpload1.HasFile)
{
string fileName = FileUpload1.FileName;
FileUpload1.SaveAs(strRealPath + fileName);
//Now insert the file into the database.
}
f.photo = Convert.ToString(FileUpload1.FileBytes);
But I find anything added .I use the debugger he tell me that posted file is null
Thanks
Firstly, your form should be encrypted as multipart/form-data. Add parameter to your form tag like below:
enctype = "multipart/form-data"
Secondly you have to send file as controller parameter HttpPostedFile.
This tutorial will be useful for you. Let us know, does it work properly.
===EDIT===
When it comes to database. You have to have column of binary type (varbinary[max]), and you
should try save it there (remember about try/catch). To read content of the file, use stream reader.

The excelsheet was uploaded different machine i.e.,Windows or Sun solories.How can i shown the same excelsheet when user select report using Servlets

In my application,we are having two different machines i.e.,Sun Solories and window machine.User will uploaded ms-excelsheet any one machine.So,I want to display same excelsheet when i uploaded completed in the report.User wlll select report any machine at any time.So,I need how will proceseed this scenario.I am thing i will save excelsheet using clob object in oracle.But i don't its right or not?.Please give any solutions in this
scenario
It really doesn't matter what operating system the client or server runs as long as you treat binary files properly in the server side and the client has the necessary software installed to open the desired binary file.
First, you need to store binary data in a blob, not a clob. A clob is intended for character/text data, not for binary data. Binary data would otherwise only be malformed. Once you've fixed that, then just create a servlet which gets an InputStream of the blob using ResultSet#getBinaryStream() based on a request parameter or pathinfo and then streams it to the OutputStream of the HTTP response along with a set of proper response headers which instructs the browser what to do with it.
For example,
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
InputStream input = getInputStreamFromDatabase(filename); // Do the JDBC job there.
OutputStream output = response.getOutputStream();
response.setHeader("Content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
// Now write input to output the usual way.
Then you can invoke it by http://example.com/context/excelservlet/filename.xls.

Opening an image in vb to send into a database - Asp.Net

I'm currently patching an asp.net program where I need to be able to send an image to an SQL Server 2005 DB. It works fine when I use the asp:fileupload control, but the trick is that when the user deletes the image, I'm supposed to replace it with an image from the server saying "empty", in code-behind.
I know how to open, use and save text files in vb, but I can't find any information anywhere on how to open an image / binary file in a similar manner so that I can use it as an sql-parameter on the update query.
Below is an example of how easy it is to use a file from the fileupload control.
Dim t_id As Integer = Convert.ToInt32(Request.QueryString("id"))
open()
Dim picture As New SqlParameter("#picture", pictureFileUpload.FileBytes)
Dim id As New SqlParameter("#id", t_id)
myCommand = New SqlCommand("spChangeImage")
myCommand.CommandType = CommandType.StoredProcedure
myCommand.Connection = conn
myCommand.Parameters.Add(picture)
myCommand.Parameters.Add(id)
myCommand.ExecuteNonQuery()
close()
Now I need a way to open an image file and set it as a parameter in a similar manner, but I've no clue as to how to go about doing that. All the search results are focused on opening and viewing an image in html, I just need the binary to use it in the query. I'm trying to use binaryreader but even then I've no idea how to actually map the file to begin with.
Thanks in advance for any help!
Personally, I wouldn't store this image in the database when the user deletes their value. I would set the column to null. When writing the image I would detect if the column is null, then read the file and write it to the response. If you do this, then you won't need to accumulate anything into a local buffer, you can just write each buffer to the response as it is read. You can use FileInfo.Length to determine the content length of the response.
If you insist on putting the image in the DB, you can also use FileInfo.Length to determine the size of buffer you need to hold the image. Use your BinaryReader to read this length of bytes into the buffer. The buffer then becomes your parameter to the SQL command.
this might help.

Downloading >10,000 rows from database table in asp.net

How should I go about providing download functionality on an asp.net page to download a series of rows from a database table represented as a linq2sql class that only has primitive types for members (ideally into a format that can be easily read by Excel)?
E.g.
public class Customer
{
public int CustomerID;
public string FirstName;
public string LastName;
}
What I have tried so far.
Initially I created a DataTable, added all the Customer data to this table and bound it to a DataGrid, then had a download button that called DataGrid1.RenderControl to an HtmlTextWriter that was then written to the response (with content type "application/vnd.ms-excel") and that worked fine for a small number of customers.
However, now the number of rows in this table is >10,000 and is expected to reach upwards of 100,000, so it is becoming prohibitive to display all this data on the page before the user can click the download button.
So the question is, how can I provide the ability to download all this data without having to display it all on a DataGrid first?
After the user requests the download, you could write the data to a file (.CSV, Excel, XML, etc.) on the server, then send a redirect to the file URL.
I have used the following method on Matt Berseth blog for large record sets.
Export GridView to Excel
If you have issues with the request timing out try increasing the http request time in the web.config
Besides the reasonable suggestion to save the data on server first to a file in one of the answers here, I would like to also point out that there is no reason to use a DataGrid (it’s one of you questions as well). DataGrid is overkill for almost anything. You can just iterate over the records, and save them directly using HtmlTextWriter, TextWriter (or just Response.Write or similar) to the server file or to a client output stream. It seems to me like an obvious answer, so I must be missing something.
Given the number of records, you may run into a number of problems. If you write directly to the client output stream, and buffer all data on server first, it may be a strain on the server. But maybe not; it depends on the amount of memory on the serer, the actual data size and how often people will be downloading the data. This method has the advantage of not blocking a database connection for too long. Alternatively, you can write directly to the client output stream as you iterate. This may block the database connection for too long as it depends on the download speed of the client. But again; it your application is of a small or medium size (in audience) then anything is fine.
You should definitely check out the FileHelpers library. It's a freeware, excellent utility set of classes to handle just this situation - import and export of data, from text files; either delimited (like CSV), or fixed width.
It offer a gazillion of options and ways of doing things, and it's FREE, and it works really well in various projects that I'm using it in. You can export a DataSet, an array, a list of objects - whatever it is you have.
It even has import/export for Excel files, too - so you really get a bunch of choices.
Just start using FileHelpers - it'll save you so much boring typing and stuff, you won't believe it :-)
Marc
Just a word of warning, Excel has a limitation on the number of rows of data - ~65k. CSV will be fine, but if your customers are importing the file into Excel they will encounter that limitation.
Why not allow them to page through the data, perhaps sorting it before paging, and then give them a button to just get everything as a cvs file.
This seems like something that DLinq would do well, both the paging, and writing it out, as it can just fetch one row at a time, so you don't read in all 100k rows before processing them.
So, for cvs, you just need to use a different LINQ query to get all of the rows, then start to save them, separating each cell by a separator, generally a comma or tab. That could be something picked by the user, perhaps.
OK, I think you are talking too many rows to do a DataReader and then loop thru to create the cvs file. The only workable way will be to run:
SQLCMD -S MyInstance -E -d MyDB -i MySelect.sql -o MyOutput.csv -s
For how to run this from ASP.Net code see here. Then once that is done, your ASP.Net page will continue with:
string fileName = "MyOutput.csv";
string filePath = Server.MapPath("~/"+fileName);
Response.Clear();
Response.AppendHeader("content-disposition",
"attachment; filename=" + fileName);
Response.ContentType = "application/octet-stream";
Response.WriteFile(filePath);
Response.Flush();
Response.End();
This will give the user the popup to save the file. If you think more than one of these will happen at a time you will have to adjust this.
So after a bit of research, the solution I ended up trying first was to use a slightly modified version of the code sample from http://www.asp.net/learn/videos/video-449.aspx and format each row value in my DataTable for CSV using the following code to try to avoid potentially problematic text:
private static string FormatForCsv(object value)
{
var stringValue = value == null ? string.Empty : value.ToString();
if (stringValue.Contains("\"")) { stringValue = stringValue.Replace("\"", "\"\""); }
return "\"" + stringValue + "\"";
}
For anyone who is curious about the above, I'm basically surrounding each value in quotes and also escaping any existing quotes by making them double quotes. I.e.
My Dog => "My Dog"
My "Happy" Dog => "My ""Happy"" Dog"
This appears to be doing the trick for now for small numbers of records. I will try it soon with the >10,000 records and see how it goes.
Edit: This solution has worked well in production for thousands of records.

Resources