Click here to Skip to main content
15,894,036 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am trying to download a file from database but its giving me an error called Unable to cast object of type 'System.String' to type 'System.Byte[]' on the line : Response.AddHeader("Content-Length", bytes.ToString());

Please tell me how can I cast string to byte in my case, thank you in advance.

I have a column named SaleFileName from which I want to download a file.

Aspx code:

ASP.NET
<asp:TemplateField HeaderText="RecieptName" SortExpression="RecieptName">
                               <ItemTemplate>
                                   <asp:LinkButton ID="LinkButton1" runat="server" CommandName="Download" CommandArgument='<%# Bind("SaleName") %>' Text='<%# Bind("SaleName") %>' ></asp:LinkButton>
                               </ItemTemplate>
                           </asp:TemplateField>

Code Behind File:

C#
protected void gridContributions_RowCommand(object sender, GridViewCommandEventArgs e)
   {
       if (e.CommandName == "Download")
       {

           // make sure fileName  contains only file name like 'test.pdf'
           string FileName = Convert.ToString(e.CommandArgument);

           // make sure filePath  contains file path like 'Uploads/Scheme/test.pdf'

            string FilePath = e.CommandArgument.ToString();


           string connectionString = WebConfigurationManager.ConnectionStrings["ConnectionString2"].ConnectionString;
           // SqlConnection con = new SqlConnection(connectionString);

          // byte[] bytes;
           //string ContentType;

           using (SqlConnection con = new SqlConnection(connectionString))
           {
               using (SqlCommand cmd = new SqlCommand())
               {
                   cmd.CommandText = "selectSaleFileName from Contributions where SaleFileName = @SaleFileName";
                   cmd.Parameters.AddWithValue("@SaleFileName", FileName);
                   //d.CommandType = CommandType.StoredProcedure;
                   cmd.Connection = con;
                   con.Open();
                   using ( SqlDataReader sdr = cmd.ExecuteReader())

                   {
                       sdr.Read();
                       bytes = (byte[])sdr["SaleFileName"];
                      //byte data = System.Text.Encoding.Unicode.GetBytes(SaleFileName.ToString);

                   }
                   con.Close();

               }
           }
           Response.Clear();
           Response.Buffer = true;

           // Read the original file from disk
            FileStream myFileStream = new FileStream( FilePath  ,FileMode.Open);
           long FileSize = myFileStream.Length;
           byte[] Buffer = new byte[Convert.ToInt32(FileSize)];
           myFileStream.Read(Buffer, 0, Convert.ToInt32(FileSize));
           myFileStream.Close();




          // // Tell the browse stuff about the file
           Response.AddHeader("Content-Length", bytes.ToString());
          // Response.AddHeader("Content-Length", FileNam
               //Response.AddHeader("Content-Disposition", "inline; filename=" & fileName.Replace(" ", "_"));
           Response.AddHeader("Content-Disposition", "attachment; FileName=" + FileName + ";");
           Response.TransmitFile(FileName);
           Response.ContentType = "application/octet-stream";

           // Send the data to the browser
           Response.BinaryWrite(Buffer);
           Response.End();
       }
   }
Posted
Updated 10-Jun-14 8:33am
v3
Comments
LLLLGGGG 10-Jun-14 14:21pm    
I think that you cannot convert a database field into a byte array using an explicit cast.
This byte[] data = System.Text.Encoding.Unicode.GetBytes(sdr["SaleFileName"].ToString()); should work fine.. but I'm not so sure of that.. try and see what happens..
Pakala Thulasiram 7-Jun-16 3:02am    
doubt

First of all, if your array of bytes really represent some text data (the question is: where did you get it?), ToString() won't help you, it will return the string "System.Byte[]", instead of what you probably expected. This is a big mistake, but not the one you are reporting. The line you pointed out would not show the compilation error. You simply present wrong information on the error. Ether the line or the error message is different.

I have no idea why are you trying to stick bytes into some header and have no idea what is in this array. I can only guess that you want to create a header "Content-Length" showing the length equal to the data size, where your data is in bytes. Then you would need to use
C#
Response.AddHeader("Content-Length", bytes.Length.ToString());

If your purpose is different, please feel free to clarify and ask some follow-up questions.

However, I would seriously advise you to gain some confidence on much simpler projects than the one you are trying to do. Better less but better.

—SA
 
Share this answer
 
v3
Ignoring that your code looks odd:
C#
cmd.CommandText = "selectSaleFileName from Contributions where SaleFileName = @SaleFileName";
Should have a space between "select" and "SaleFileName"

I assume that the error occurs here:
C#
bytes = (byte[])sdr["SaleFileName"];
Which implies that the data returned from your DB is a string: i.e. it came from a VARCHAR or NVARCHAR column. In that case, it's probably a bigger mistake than you think...

You can convert a string into a byte array; your commented out code almost does that.
But...the chances are that using a VARCHAR or NVARCHAR column to store your data has messed up your file content already: they do not hold byte values well, and binary information such as images, videos, MP3, and so on do not generally survive the process. Unless you know, absolutely and certainly, that your files will always be text based files such as .TXT or .XML and so forth, then you should always use VARBINARY(MAX) and store the binary data directly via a parameterized query. You can then use your existing code to retrieve the byte array and process it.
 
Share this answer
 
You can use this below code if file is stored in database

C#
private byte[] ReadFileFromDatabase(string FileName) {
    string connectionString = WebConfigurationManager.ConnectionStrings["ConnectionString2"].ConnectionString;
    byte[] bytes;

    using (SqlConnection con = new SqlConnection(connectionString))
    {
        using (SqlCommand cmd = new SqlCommand())
        {
            cmd.CommandText = "selectSaleFileName from Contributions where SaleFileName = @SaleFileName";
            cmd.Parameters.AddWithValue("@SaleFileName", FileName);
            cmd.Connection = con;
            con.Open();

            using ( SqlDataReader sdr = cmd.ExecuteReader())
            {
               if (sdr.Read() )
                  bytes = (byte[])sdr["SaleFileName"];
            }
            con.Close();
        }
    }

    return bytes;
}

protected void gridContributions_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "Download")
    {
        string FileName = Convert.ToString(e.CommandArgument);
        byte[] bytes = ReadFileFromDatabase(FileName);

        Response.Clear()
        Response.ContentType = "application/octet-stream"
        Response.AddHeader("Content-Disposition", "attachment; FileName=" + FileName + ";");
        Response.BinaryWrite(bytes)
        Response.End()
    }
}


and if file is outside database then,
C#
public static void DownloadFile(string path, string contentType)
{
    FileInfo file = new FileInfo(path);
    if (file.Exists)
    {
        Response.Clear();
        Response.ClearHeaders();
        Response.ClearContent();

        Response.AddHeader("Content-Type", contentType);
        Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
        Response.AddHeader("Content-Length", file.Length.ToString());

        Response.Flush();
        Response.TransmitFile(file.FullName);
        Response.End();
    }
}

http://www.ati-erp.com
 
Share this answer
 
Comments
phil.o 10-Jun-14 16:13pm    
What is this link for? Are you trying to do a stealth-advertising?
Espen Harlinn 11-Jun-14 11:45am    
5'ed - for the second code sample, as I guess the byte[] cast during the read from the db is just a bug, and that the file is located outside the DB :-)
If your data is stored in a binary or varbinary column, then you can get the bytes directly with:
C#
bytes = sdr.GetBytes("SaleFileName");


If your data is stored in a varchar or nvarchar column, but represents some binary data, chances are that it has been encoded. Most probably in Base 64. You can then get the bytes with:
C#
string encoded = sdr.GetString("SaleFileName");
bytes = Convert.FromBase64String(encoded);

(but here I'm just guessing a possible encoding, others are still possible, you'll have to ask that to the one who maintains the database)

If your data is stored in a varchar or nvarchar column, and really represents a string, then there's no need to get any byte array in the first place.

The name of the column (SaleFileName) could suggest the column does not hold the data itself, but the physical path to the file holding it. In this case, you will have to open a Stream from the path obtained from database.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900