Couple of things:
0) Never use
SELECT * FROM
- it returns all the columns in a table in an "unknown" order which may be subject to change later. That's both wasteful as some of the columns may not be needed, and error-prone if you rely on the order in your code. Instead, list only the columns you are interested in, and use the column name as the index to retrieve the data:
sqlcmd = new SqlCommand("SELECT fcontent FROM PDFupload WHERE ID=@ID", sqlcon);
sqlcmd.Parameters.AddWithValue("@ID", id);
...
dbbyte = (byte[])dt.Rows[0]["fcontent"];
And check the numbe of columns you get back as well!
1) Never concatenate strings to build a SQL command. It leaves you wide open to accidental or deliberate SQL Injection attack which can destroy your entire database. Always use Parameterized queries instead, as shown above.
When you concatenate strings, you cause problems because SQL receives commands like:
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
The quote the user added terminates the string as far as SQL is concerned and you get problems. But it could be worse. If I come along and type this instead: "x';DROP TABLE MyTable;--" Then SQL receives a very different command:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;
Which SQL sees as three separate commands:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
A perfectly valid SELECT
DROP TABLE MyTable;
A perfectly valid "delete the table" command
And everything else is a comment.
So it does: selects any matching rows, deletes the table from the DB, and ignores anything else.
So ALWAYS use parameterized queries! Or be prepared to restore your DB from backup frequently. You do take backups regularly, don't you?
2) Never store files in the root of any drive: for boot devices, that is restricted for security reasons, and it's likely to become more restricted over time, not less. Use a subdirectory instead. In this case, because it's a temporary file, you should use the
Path.GetTempPath Method (System.IO) | Microsoft Docs[
^] to find the TEMP folder, and then create a temporary file within that - I tend to use GUID values to generate the filename:
string path = Path.GetTempPath();
string file = Guid.NewGuid().ToString("N") + ".pdf";
string filepath = Path.Combine(path, file);
Using the Combine method ensures that path dividers are inserted as required automatically.
And you can simplify your code a bit as well:
string path = Path.GetTempPath();
string file = Guid.NewGuid().ToString("N") + ".pdf";
string filepath = Path.Combine(path, file);
File.WriteAllBytes(filepath, dbbyte);
Process p = new Process();
p.StartInfo.FileName = filepath;
p.Start();
When I place a valid PDF file into dbbyte, it opens using my default PDF reader.
So if you try that and it doesn't work it's most likely that you saved the wrong data into the DB, or saved it badly.