I have this code:
public void OpenFile(string fileName)
{
var url = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
using (var fileStream = new FileStream(url, FileMode.Open))
{
byte[] bytes = new byte[fileStream.Length];
int numBytesToRead = (int)fileStream.Length;
int numBytesRead = 0;
fileStream.Read(bytes,numBytesRead, numBytesToRead);
}
}
That code is working fine, but I want to show that file in the browser, I'm executing this method on click in the name of the file, parameters are working great, which is the other code that I need to put to show the file in the browser? Mostly the files are going to be .doc and .pdf. How can I show the documents in the browser??
You can return a FileStreamResult from your action method. Change the method return type from void to ActionResult
public ActionResult OpenFile(string fileName)
{
var pathToTheFile = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
var fileStream = new FileStream(pathToTheFile,
FileMode.Open,
FileAccess.Read
);
return new FileStreamResult(fileStream, MimeMapping.GetMimeMapping(fileName));
}
Related
I have a variable which holds a pdf stream , this variable is of type System.Threading.Tasks.Task<Stream>. I want to save this pdf stream in a pdf file but I am not sure how to do so . Below is a piece of code I tried to work on . Any ideas as to what I can try to save this stream in a file
System.Threading.Tasks.Task<Stream> pdf = //Some logic here which gets a pdf stream
I want to store the pdf content in the variable in a file as a pdf
For that I worote the method
public static void SaveStreamAsFile(string filePath, System.Threading.Tasks.Task<Stream> inputStream, string fileName)
{
string path = Path.Combine(filePath, fileName);
using (FileStream outputFileStream = new FileStream(path, FileMode.Create))
{
// logic
}
}
Read the input stream and write it to the output stream..
public static async Task SaveStreamAsFile(string filePath, System.Threading.Tasks.Task<Stream> inputStream, string fileName)
{
var stream = await inputStream;
var path = Path.Combine(filePath, fileName);
var bytesInStream = new byte[stream.Length];
await stream.ReadAsync(bytesInStream, 0, (int) bytesInStream.Length);
using (var outputFileStream = new FileStream(path, FileMode.Create))
{
await outputFileStream.WriteAsync(bytesInStream, 0, bytesInStream.Length);
}
}
I need the user to be able to download png images from my site. When the mthod runs it completes without errors but no image is downloaded. I do not need the user to see a pop-up dialog thought it is certainly helpful. This is what I have right now:
public async Task<IActionResult> DownloadImage(string filename)
{
var path = Path.GetFullPath("./wwwroot/images/school-assets/" + filename);
MemoryStream memory = new MemoryStream();
using (FileStream stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "image/png", "download");
}
This method is called by an ajax call in the view that looks like this
$.ajax({
url: "./MyHome/DownloadImage",
type: "Get",
data: {filename : filename},
success: function (file) {
},
error: function (request, status, error) {
console.log(request.responseText);
}
});
}
Edit:
If i console.log file in the success portion i see a string of bytes so I know it is creating the file but not letting the user get to i. I have tried content disposition and creating a physical file result as suggested.
For File, you need to provide the file name with file extension, otherwise, the downloaded file will not be able to open.
Try something like
public async Task<IActionResult> DownloadImage(string filename)
{
var path = Path.GetFullPath("./wwwroot/images/school-assets/" + filename);
MemoryStream memory = new MemoryStream();
using (FileStream stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "image/png", Path.GetFileName(path));
}
You need to set the content dispositon type to enable direct downloading of the file :
public IActionResult OnGetPng()
{
var bytes = System.IO.File.ReadAllBytes("test.png");
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "test.png",
Inline = false
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
return File(bytes, "image/png");
}
If you prefer you can also make use of the PhysicalFileResult type which takes care of your stream and return FileResult from your controller. In that case your code looks like this:
var fn = Path.Combine(env.WebRootPath, "test.png");
var contentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
return new PhysicalFileResult(fn, "image/jpeg");
To get access to the WebRootPath you have to inject IHostingEnvironment env into your constructor.
#Caleb sir from below code you can download png file.
Download png file from folder
[HttpGet]
public FileStreamResult DownloadPngFile(string fileName)
{
var stream = new FileStream(Directory.GetCurrentDirectory() + "\\wwwroot\\images\\school-assets\\" + fileName, FileMode.Open);
return new FileStreamResult(stream, "image/png");
}
Download png file from database
[HttpGet]
public FileStreamResult DownloadPngFileFromDataBase(string id)
{
var _fileUpload = _db.ImageFileUpload.SingleOrDefault(aa => aa.fileid == id);
// _fileUpload.FileContent column type is byte
MemoryStream ms = new MemoryStream(_fileUpload.FileContent);
return new FileStreamResult(ms, "image/png");
}
For more info please also see this question and answer. Download Pdf file in asp.net core (accepted answer) and one more extra link
Download files in asp.net core
This code can save photos from URL addresses in the server folder.
private readonly Lazy<HttpClient> _client;
In constructor:
_client = new Lazy<HttpClient>(() => clientFactory.CreateClient());
That is better to use lazy loading in a way the server will not spend additional resources to create HttpClient immediately.
public async Task<string> SavePhotoInFolder(string url)
{
string photoPath = $"/Photos/{Guid.NewGuid()}.jpeg";
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
using (
Stream contentStream = await (await _client.Value.SendAsync(request)).Content.ReadAsStreamAsync(),
stream = new FileStream($"{_appEnvironment.WebRootPath}{photoPath}", FileMode.Create))
{
await contentStream.CopyToAsync(stream);
}
return photoPath;
}
You can use HttpClient
using (var client = new HttpClient())
{
try
{
using var result = await client.GetAsync($"http://{url}");
if (result.IsSuccessStatusCode)
{
return await result.Content.ReadAsByteArrayAsync();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.InnerException);
}
}
I am using a third party library in which one of the methods returns FileStreamResult.
public FileStreamResult GenerateFile(OutFormat format, dynamic params);
An action in my controller calls this method:
public ActionResult GenerateExcel()
{
Utils.XCore core = new Utils.XCore(...); // where ... are contructor params
// ... other codes here ...
return core.GenerateFile(OutFormat.EXCEL, new { FileName = "Report" });
}
This is going to be fine but sometimes I want to merge multiple Excel worksheets into one which is something like this:
public ActionResult GenerateExcel()
{
Utils.XCore core = new Utils.XCore(...); // where ... are contructor params
// ... other codes here ...
var excel1 = core.GenerateFile(OutFormat.EXCEL, new { FileName = "rpt1" });
var excel2 = core.GenerateFile(OutFormat.EXCEL, new { FileName = "rpt2" });
var excel3 = core.GenerateFile(OutFormat.EXCEL, new { FileName = "rpt3" });
var finalContent = combineFile(excel1, excel2, excel3);
return new FileStreamResult(finalContent, "application/ms-excel")
{
FileDownloadName = "Report.xls"
};
}
My problem now is I don't know how to get the content from FileStreamResult. Any ideas on how to do it? Even comments containing weblinks are pretty much appreciated. Thanks!
If I correctly understand your question, you want to process/get the content from FileStreamResult. The class contains a property called FileStream which is a Stream object. Now, the stream object can now be saved as a file using the following modified code from this site:
private void streamToFile(Stream fileStream, string filePath)
{
using (FileStream writeStream = new FileStream(filePath,
FileMode.Create,
FileAccess.Write))
{
int length = 1024;
Byte[] buffer = new Byte[length];
int bytesRead = fileStream.Read(buffer, 0, length);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = fileStream.Read(buffer, 0, length);
}
fileStream.Close();
writeStream.Close();
}
}
and the following is how to use:
var excel1 = core.GenerateFile(OutFormat.EXCEL, new { FileName = "rpt1" });
string filePath = "C:\\yourFileName.xls"; // path of your newly saved file
using (Stream reportStream = excel1.FileStream)
{
streamToFile(reportStream, filePath);
}
I have created one WCF service that will upload the file. and after using that service I am trying to upload the file I am able to successfully upload the file but there is some issue with the FILESTREAM class.
The moment i clicked the button to upload the file when i checked by debugging the application i get to know that stream object is null.
I am passing the object of stream class to the WCF method.
But due to some issue that stream object is getting null.
due to that null object of stream class, image which is uploded getting empty in my folder
This is my code that I am using to upload the file
if (FileUpload1.HasFile)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(FileUpload1.PostedFile.FileName);
FileTransferServiceReference.ITransferService clientUpload = new FileTransferServiceReference.TransferServiceClient("BasicHttpBinding_ITransferService");
FileTransferServiceReference.RemoteFileInfo uploadRequestInfo = new RemoteFileInfo();
string Path = System.IO.Path.GetDirectoryName(FileUpload1.FileName);
using (System.IO.FileStream stream = new System.IO.FileStream(FileUpload1.FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
uploadRequestInfo.FileName = FileUpload1.FileName;
uploadRequestInfo.Length = fileInfo.Length;
uploadRequestInfo.FileByteStream = stream;
clientUpload.UploadFile(uploadRequestInfo);
}
}
Code for WCF Service
public RemoteFileInfo DownloadFile(DownloadRequest request)
{
RemoteFileInfo result = new RemoteFileInfo();
try
{
// get some info about the input file
string filePath = System.IO.Path.Combine(#"c:\Uploadfiles", request.FileName);
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
// check if exists
if (!fileInfo.Exists) throw new System.IO.FileNotFoundException("File not found", request.FileName);
// open stream
System.IO.FileStream stream = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
// return result
result.FileName = request.FileName;
result.Length = fileInfo.Length;
result.FileByteStream = stream;
}
catch (Exception ex)
{
}
return result;
}
public void UploadFile(RemoteFileInfo request)
{
FileStream targetStream = null;
Stream sourceStream = request.FileByteStream;
string uploadFolder = #"C:\upload\";
if (!Directory.Exists(uploadFolder))
{
Directory.CreateDirectory(uploadFolder);
}
string filePath = Path.Combine(uploadFolder, request.FileName);
using (targetStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
const int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
targetStream.Write(buffer, 0, count);
}
targetStream.Close();
sourceStream.Close();
}
}
}
Spot the difference:
string uploadFolder = #"C:\upload\";
...
string filePath = System.IO.Path.Combine(#"c:\Uploadfiles", request.FileName);
As a general tip you might put your upload file path into an external configuration file, so that you can change it when you move your application onto a server where you need to store the data on a different drive or in a specific location.
Also that way you are always calling the same configuration entry so your upload path name is definitely going to be the same everywhere.
I have a return File that is offering to download a file but is also downloading the file to another location, I would just like it to offer to download to the user one file, i.e. it reads the initial data from memory, so the first argument in the return File is a MemoryStream of some sort, but I can't figure out how to do it
[HttpPost]
public FilePathResult FileToFasta(F2FModel model)
{
string FullText = new StreamReader(model.File.InputStream).ReadToEnd();
TextLayer layer = new TextLayer(FullText);
string outputFile = layer.WriteToFasta();
String mydatetime = DateTime.Now.ToString("MMddyyyy");
string FileName = String.Format("TextFile{0}.txt", mydatetime);
string FilePath = #"F:\test\" + FileName;
FileInfo info = new FileInfo(FilePath);
if (!info.Exists)
{
using (StreamWriter writer = info.CreateText())
{
writer.Write(outputFile);
}
}
return File(FilePath, "text/plain", FileName);
}
Thanks
MemoryStream can be used with FileStreamResult, for example like this:
[HttpPost]
public FilePathResult FileToFasta(F2FModel model)
{
string FullText = new StreamReader(model.File.InputStream).ReadToEnd();
TextLayer layer = new TextLayer(FullText);
string outputFile = layer.WriteToFasta();
string mydatetime = DateTime.Now.ToString("MMddyyyy");
string FileName = String.Format("TextFile{0}.txt", mydatetime);
//Use different encoding if needed
byte[] outputArray = Encoding.Unicode.GetBytes(outputFile);
MemoryStream outputStream = new MemoryStream(outputArray);
//FileStreamResult will close the stream for you so don't worry
return new FileStreamResult(outputStream, "text/plain") { FileDownloadName = FileName };
}