I've been trying to convert a file that was stored into my database as byte array, into a downloadable file on my website. The link to download seemingly produces a line of recurring gibberish.
My document has been stored within a database as this class
public class User
{
public string ResumeName { get; set; }
public byte[] Resume { get; set; }
public string ResumeContentType { get; set; }
}
In order to retrieve the information back as a document, I use this function
public IActionResult Download(byte[] filebytes, string type, string name)
{
return File(filebytes, type, name);
}
The webpage itself uses this action link to produce the button to create a download link
@Html.ActionLink("Download File", "Download", new {
filebytes = @UserManager.GetUserAsync(User).Result.Resume,
type = @UserManager.GetUserAsync(User).Result.ResumeContentType,
name = @UserManager.GetUserAsync(User).Result.ResumeName
})
When the code is run, clicking the link doesn't do anything visible which means I am unable to see how it has gone wrong. However, opening the link in a new tab produces this long link that has been shortened greatly
https://localhost:7095/Home/Download?filebytes=80&filebytes=75&......(this repeated several hundred times)...... filebytes=0&filebytes=0&filebytes=0&filebytes=0&type=application%2Fvnd.openxmlformatsofficedocument.wordprocessingml.document&name=__xid-43512761_1.docx
Why does this occur and is there a way to fix it?
Take a step back, because you took a wrong turn somewhere a while ago. Consider what this does:
public IActionResult Download(byte[] filebytes, string type, string name)
{
return File(filebytes, type, name);
}
It returns a file to the client. But where does it get the data for that file? From the client. What you have is a scenario where:
Potential issues in this scenario include data encoding problems, limits on URL length, and the fact that it's just plain unnecessary.
Scrap it.
For images and such it's not uncommon to embed the data on the page to render the image. For a downloadable file though, it doesn't make much sense. Instead, include only an identifier that can be used by the server to fetch the file from data. For example:
@Html.ActionLink("Download File", "Download", new { userId = User.Id })
Now the link only contains an ID for that user. (I'm guessing on the actual .Id
field for demonstration purposes only. Use whatever value you use to identify your User
record.)
Then the Download
action accepts that value and fetches the data:
public IActionResult Download(int userId)
{
// fetch a "user" object here based on that ID,
// then use that object to populate the below variables...
return File(filebytes, type, name);
}
Again, this is all for demonstration purposes only. In fact, if the user is always the current logged-in user and is always known then you don't even need that userId
, just use the current user.
Either way, the point is that you don't need (or even want) to pass around the entire contents of the file back and forth between the server and the client. Just display the data that page needs, and include a link to a separate controller action which just returns the file.