This code is supposed to download a file using mvc3 controller
public FilePathResult GetFileFromDisk(String file)
{
String path = AppDomain.CurrentDomain.BaseDirectory + "AppData/";
String contentType = "text/plain";
return File(path+file, contentType, file);
}
View part :
#Html.ActionLink("Download", "GetFileFromDisk","Upload", new { file = "textfile" },null);
But when i click the link I am getting this error
Could not find a part of the path 'D:\Project\FileUploadDownload\FileUploadDownload\AppData\textfile'.
[DirectoryNotFoundException: Could not find a part of the path 'D:\Project\FileUploadDownload\FileUploadDownload\AppData\textfile'.]
Why the foldername is repeating in the file path? Please offer a solution...
Try like this:
public ActionResult GetFileFromDisk(string file)
{
var appData = Server.MapPath("~/App_Data");
var path = Path.Combine(appData, file);
path = Path.GetFullPath(path);
if (!path.StartsWith(appData))
{
// Ensure that we are serving file only inside the App_Data folder
// and block requests outside like "../web.config"
throw new HttpException(403, "Forbidden");
}
if (!System.IO.File.Exists(path))
{
return HttpNotFound();
}
var contentType = "text/plain";
return File(path, contentType, Path.GetFileName(path));
}
Related
I am using ASP.NET WEB API to upload image to server. But when i upload the source code of my web api to gearhost.com and make a post request. I am unable to post the image. This is my web api controller code:
[Route("upload")]
[HttpPost]
public async Task<string> Upload()
{
var ctx = HttpContext.Current;
var root = ctx.Server.MapPath("/uploads/");
var provider = new MultipartFormDataStreamProvider(root);
try
{
await Request.Content
.ReadAsMultipartAsync(provider);
foreach (var file in provider.FileData)
{
var name = file.Headers
.ContentDisposition
.FileName;
// remove double quotes from string.
name = name.Trim('"');
var localFileName = file.LocalFileName;
var filePath = Path.Combine(root, "files", name);
// File.Move(localFileName, filePath);
// SaveFilePathSQLServerADO(localFileName, filePath);
// SaveFileBinarySQLServerADO(localFileName, name);
// SaveFilePathSQLServerEF(localFileName, filePath);
SaveFileBinarySQLServerEF(localFileName, name, filePath);
if (File.Exists(localFileName))
File.Delete(localFileName);
}
}
catch
{
return "Error";
}
return "File uploaded successfully!";
}
public void SaveFileBinarySQLServerEF(string localFile, string fileName, string filePath)
{
// 1) Get file binary
byte[] fileBytes;
using (var fs = new FileStream(localFile, FileMode.Open, FileAccess.Read))
{
fileBytes = new byte[fs.Length];
fs.Read(fileBytes, 0, Convert.ToInt32(fs.Length));
}
// 2) Create a Files object
var file = new tblimage()
{
Data = fileBytes,
Names = fileName,
ContentType = filePath
};
// 3) Add and save it in database
using (var ctx = new coachEntities())
{
ctx.tblimages.Add(file);
ctx.SaveChanges();
}
}
Here is the successful call from localhost:
Image posted through localhost
However when deployed the same code and make request through postman then I get this error:
Image posted through live server
Maybe, "uploads" doesn't have write permission
Check the permission in your uploads folder.
Go to properties-- security
Give the read write permission.
Though it is not good idea to return the exception details in live code. As you are not maintaining log. For testing, Please return the exception details. Also, how are you getting the response like "unable to upload, try again" because it is not there in your code
please review my code as I am not able to attach any file in EmailMessageBuilder.
Also I need to understand about the ContentType, what should I pass in ContentType?
FileData filedata = await CrossFilePicker.Current.PickFile();
String Path = CrossGetLocalFilePath.Current.GetLocalPath(filedata.FileName);
var emailMessenger = CrossMessaging.Current.EmailMessenger;
if (emailMessenger.CanSendEmail)
{
var email = new EmailMessageBuilder()
.To("to.plugins#xamarin.com")
.Subject("Xamarin Messaging Plugin")
.Body("Well hello there from Xam.Messaging.Plugin")
.WithAttachment(Path, "image/jpeg")
.Build();
emailMessenger.SendEmail(email);
}
I am using above code in Xamarin.forms (Portable), my attachment could be an image, video or any file.
Getting error:
Failed to attach file due to IO error.
I never used the CrossFilePicker plugin and CrossGetLocalFilePath plugin before but I find the source code here:
CrossFilePicker : https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows/tree/master/FilePicker/FilePicker
CrossGetLocalFilePath:https://github.com/bradyjoslin/GetLocalFilePathPlugin/blob/master/GetLocalFilePath/GetLocalFilePath.Plugin.Android/GetLocalFilePathImplementation.cs
This is the FileData object you got when you call CrossFilePicker.Current.PickFile();
namespace Plugin.FilePicker.Abstractions
{
public class FileData
{
public byte[] DataArray { get; set; }
public string FileName { get; set; }
}
}
DataArray is your file data, and FileName is your file name. It does not contain the file path.
And you call the another plugin CrossGetLocalFilePath to get the file path according to the file name.
in the CrossGetLocalFilePath source code it just implements in Android platform:
public class GetLocalFilePathImplementation : IGetLocalFilePath
{
public string GetLocalPath(string fileName)
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
return System.IO.Path.Combine(path, fileName);
}
}
it not return the file path you want. It returned system special file path.
So in your case it is not possible to get the file path by these plugins.
But I recommend you to overwrite the CrossFilePicker plugin.
Take UWP as an example:
public class FilePickerImplementation : IFilePicker
{
public async Task<FileData> PickFile()
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.List;
picker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
picker.FileTypeFilter.Add("*");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
var array = await ReadFile(file);
return new FileData
{
DataArray = array,
FileName = file.Name
FilePath = file.Path;
};
}
else
{
return null;
}
}
This is the implementation of file picker in UWP. You can add the FilePath property in the FileData Object as the code shows before.
We can get the path if we are using the below plugin for the Media Capture and Select image from the Gallery.
Xam.Plugin.Media
Thank You.
To upload image i'am using this code:
[HttpPost]
public ActionResult Index(FotoModel model)
{
if (ModelState.IsValid)
{
if (model != null && model.File != null)
{
var fileName = Path.GetFileName(model.File.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Images"), fileName);
model.File.SaveAs(path);
return View();
}
}
return View();
}
Works fine, but is there option to change file name ?. I was trying do something like this:
fileName = FileMode(fileName, "user");
But there an exception: "System.IO.FileMode is a type but is used like a variable"
Doesn't Path.Combine() allow for combining strings into a filename? So couldn't you simply do:
var fileName = "user";
var path = Path.Combine(Server.MapPath("~/Content/Images"), fileName);
In which case use the following to strip the extension then re-add it to the new filename:
string newName = "user";
fileName = newName + fileName.Substring(fileName.LastIndexOf("."));
I have a javascript function from which I need to call a controller action to return the filestream to the UI .
I am not getting the open,save and save as dialog box.
In the cshtml file I have following function:DownloadFile
var selectUrl = '#Url.Action("Download", "Controller")' + "/" + filedetails;
$.post(selectUrl);
and in the controller I have the following code:
public ActionResult Download(string id)
return File(downloadStream, "application/octet-stream",fileName);
Please let me know is this the correct way of calling.
try this way :ActionResult
public ActionResult Download(string id)
{
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "imagefilename",
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
string contentType = "application/octet-stream";
// you are downloadStream
return File(downloadStream, contentType);
}
link here
I use C#-MVC3. I have an "export" page. I have some functions for exporting different tables from the DB, every function creates a CSV file from the table and returns a FileContentResult file to the user.
Now I want to create a button for "export all", to download all the files at once.
I tried to use ZipFile but it gets only file names and path - files that were saved on the server, not "FileContentResult" files.
So I wanted to save the "FileContentResult" files temporarily on the server, zip them and delete them - but I can't find how to save a "FileContentResult" file.
If you can help me or give me another idea, I'll glad to hear.
my solution:
public ZipFile DownloadAllToZip()
{
string path = "c:\\TempCSV";
try
{
if (Directory.Exists(path))
{
EmptyFolder(path);
}
else
{
DirectoryInfo di = Directory.CreateDirectory(path);
}
List<FileContentResult> filesToExport = GetAllCSVs();
foreach (var file in filesToExport)
{
try
{
using (FileStream stream = new FileStream(path + "\\" + file.FileDownloadName, FileMode.CreateNew))
{
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
{
byte[] buffer = file.FileContents;
stream.Write(buffer, 0, buffer.Length);
writer.Close();
}
}
}
catch { }
}
}
catch{ }
Response.Clear();
Response.BufferOutput = false;
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "attachment; filename=MaterialAssetTracker.zip");
ZipFile zip= new ZipFile();
using (zip)
{
zip.CompressionLevel = CompressionLevel.None;
zip.AddSelectedFiles("*.csv", path + "\\", "", false);
zip.Save(Response.OutputStream);
}
Response.Close();
EmptyFolder(path);
return zip;
}