HttpPostedFileBase.SaveAs working but no file uploaded and no exceptions - c#

First, here is my code:
private Shoe ProcessForm(Shoe shoe, HttpPostedFileBase image)
{
try
{
shoe.Slug = CMSHelper.SanitizeTitle(shoe.Name);
shoe.LastModification = DateTime.Now;
if ((image != null) && (image.ContentLength > 0))
{
string fileName = String.Concat(shoe.ShoeId, Path.GetExtension(image.FileName));
shoe.Image = fileName;
string filePath = Path.Combine(Server.MapPath(shoe.ImagePath), fileName);
image.SaveAs(filePath);
}
}
catch (Exception e)
{
throw e;
}
return shoe;
}
Locally, this code works fine. Directories' permissions are fine. And it has worked before randomly on other servers (I tested this code on 4 or 5 different servers while I was testing VPS providers).
But if I try to run it from my home computer, everything passes alright, there's a file name saved in the database but no file is uploaded. And no exceptions are given!!!
I've been trying to fix this for almost three days and so much useless hours, please help me... I just don't see what's wrong with this...

I finally did a workaround which is doing very fine. I even asked at my job and everyone said there was nothing wrong at all. So screw it here's what I did:
Instead of calling .SaveAs() I made a method which is :
public static void WriteFileFromStream(Stream stream, string toFile)
{
using (FileStream fileToSave = new FileStream(toFile, FileMode.Create))
{
stream.CopyTo(fileToSave);
}
}
I call it like this:
CMSHelper.WriteFileFromStream(image.InputStream, filePath);
And that's it.

What is your view model? First of all replace (Shoe shoe, HttpPostedFileBase image) with (FormCollection formCollection). Put a breakpoint on that to see that you are getting all the submitted values. If you do then there is a problem with model binding and we'll need to address that.
Edit
Can you please put a breakpoint on
image.SaveAs(filePath);
Add a watch for fileName and filePath variables. I think that server path is not what you expect it to be, or maybe you are looking in the wrong folder all together. Tell us what are the values of those variables. Also make sure that no exception is thrown when you go past image.SaveAs(filePath);

image.FileName contains the path data and is selected by
Path.Combine(Server.MapPath(shoe.ImagePath), fileName)
Try something like:
string pathForSaving = Server.MapPath("~/Upload/Images");
string uploadFileName = System.IO.Path.GetFileName(image.FileName);
string uploadFilePathAndName = Path.Combine(pathForSaving, uploadFileName);
image.SaveAs(uploadFilePathAndName);

How are you setting shoe.ImagePath? Your issue feels like Server.MapPath is returning a value that you are not expecting.

Did you check to see if you have multiple web servers? Like a load balancer perhaps. It might not be throwing an exception because there isn't actually an exception and the file does actually exist somewhere, just not on the server you believe it is on. Just a thought (it has happened to me before).

Make sure you are using enctype="multipart/form-data" in the form
http://www.prideparrot.com/blog/archive/2012/8/uploading_and_returning_files

I also ran into the same issue posted on this thread and after a few tries of uploading a file, I refreshed the folder where the files were suppose to be and finally I saw them there. Not sure why it didn't show up the first time after the first refresh but it probably has something to do with refreshing the folder. I did the refresh from within Visual Studio and I also had the "Show All Files" button on.

Related

System.IO.File.Delete throws "The process cannot access the file because it is being used by another process"

Every time I save a file and delete it right away using the function below, I keep getting this error message: "System.IO.IOException: The process cannot access the file because it is being used by another process".
Waiting for a couple of minutes or closing visual studio seems to only unlock the files that you uploaded previously.
public static bool DeleteFiles(List<String> paths)
{ // Returns true on success
try
{
foreach (var path in paths)
{
if (File.Exists(HostingEnvironment.MapPath("~") + path))
File.Delete(HostingEnvironment.MapPath("~") + path);
}
}
catch (Exception ex)
{
return false;
}
return true;
}
I think that the way I'm saving the files may cause them to be locked. This is the code for saving the file:
if (FileUploadCtrl.HasFile)
{
filePath = Server.MapPath("~") + "/Files/" + FileUploadCtrl.FileName;
FileUploadCtrl.SaveAs(filePath)
}
When looking for an answer I've seen someone say that you need to close the streamReader but from what I understand the SaveAs method closes and disposes automatically so I really have no idea whats causing this
After some testing, I found the problem. turns out I forgot about a function I made that was called every time I saved a media file. the function returned the duration of the file and used NAudio.Wave.WaveFileReader and NAudio.Wave.Mp3FileReader methods which I forgot to close after I called them
I fixed these issues by putting those methods inside of a using statement
Here is the working function:
public static int GetMediaFileDuration(string filePath)
{
filePath = HostingEnvironment.MapPath("~") + filePath;
if (Path.GetExtension(filePath) == ".wav")
using (WaveFileReader reader = new WaveFileReader(filePath))
return Convert.ToInt32(reader.TotalTime.TotalSeconds);
else if(Path.GetExtension(filePath) == ".mp3")
using (Mp3FileReader reader = new Mp3FileReader(filePath))
return Convert.ToInt32(reader.TotalTime.TotalSeconds);
return 0;
}
The moral of the story is, to check if you are opening the file anywhere else in your project
I think that the problem is not about streamReader in here.
When you run the program, your program runs in a specific folder. Basically, That folder is locked by your program. In that case, when you close the program, it will be unlocked.
To fix the issue, I would suggest to write/delete/update to different folder.
Another solution could be to check file readOnly attribute and change this attribute which explained in here
Last solution could be using different users. What I mean is that, if you create a file with different user which not admin, you can delete with Admin user. However, I would definitely not go with this solution cuz it is too tricky to manage different users if you are not advance windows user.

How to check if file can be stored in particular location without storing/creating file?

Till now all cases I met was like:
try to store file
if file is stored that's fine
if file can not be stored tell about it (no path, no permission, etc)
Currently I am standing before problem how to check if file can be stored without storing it. In general I don't even know what to ask Google, because all returned results I got are about permissions, and general in Linux, and I need it under C#/Windows.
How such checking can be done?
Since you don't want to attempt writing to the folder, you could consider this approach.
You can put a try catch around this:
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath);
i.e.
public bool CanWriteToPath(string folderPath)
{
try
{
var ds = Directory.GetAccessControl(folderPath);
return true;
} catch (UnauthorizedAccessException)
{
return false;
}
}
It will only succeed if you have permissions.
Sorry that it still has to use a try/catch.
How about use try catch block? If any exception occurs - you can catch it and determine than can not save file. If no exception occurs, file successfully saved.
There is a Directory.GetAccessControl method and File.GetAccessControl method in File.IO namespace.
If you want to know the status before actually writing the file, check if the specified directory has write permissions for the user. If all is well, write the file. You could also use a try catch block as suggested in other answers.

"A generic error occurred in GDI+" when attempting to use Image.Save

I am developing an Outlook 2010 Add-In, and am loading an image from a serialized XML file. The image loads fine, and am able to assign it to a pictureBox object on a Winform no problem. The object is saved in
[XmlIgnore]
public Bitmap Image
{
get { return this.templateImage; }
set { this.templateImage = value; }
}
When, I attempt to save the physical file onto the harddisk however, I am doing:
string filePath = Path.Combine(dirPath, item.Id + ".jpg");
try
{
item.Image.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception e)
{
Debug.WriteLine("DEBUG::LoadImages()::Error attempting to create image::" + e.Message);
}
and am getting an A generic error occurred in GDI+. I've checked the write permissions on the folder, and it does have write permissions. I'm unsure what is wrong here. I've also changed the ImageFormat to bmp and png and so forth to see if it was a conversion problem... but it isn't. Would anybody suggest something to try?
Thank you to Simon Whitehead for answering this in the comments. He said, "3) Make sure the file is not in use by anything else (including your code)."
So the problem was that my own code was using the item.Image object, and was preventing GDI+ to call the dispose() method on it. The solution was to copy the object into a new object, then use that object to "Write." The resulting code is as follows:
try
{
using (Bitmap tempImage = new Bitmap(item.Image))
{
tempImage.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
}
}
catch (Exception e)
{
Debug.WriteLine("DEBUG::LoadImages()::Error attempting to create image::" + e.Message);
}
I too faced same error for code line:
wmImg.Save(BrandImgPath,ImageFormat.Png);
BrandImgPath = "D:/XYZ/fileName;
Found cause:
XYZ folder didn't exist in D: drive. So my code was creating this folder later. One should ensure if that path exist or not.
if (Directory.Exists(#"D:/XYZ")) return;
Hope it will help someone to solve his code mistakes.
1. Make Sure That your destination folder have read/write permission (check it twice!).
2. Using Server.MapPath is better
3. Make Sure you have free space on your destination drive or folder.
4. Most of the times we cant user Memory Streamers On Shared Servers, So we should be make sure that provider allow us to use it.
Hope Microsoft Give Detailed Exception Errors instead of "Generic GDI+ Errror" !!!
Had this issue myself, needed to check that the folder existed, GDI didn't tell me what went wrong, would have been nice.
In my case it was a spelling mistake in the path to the directory where I was saving the image:
if (Directory.Exists(directory_path))
{
image.SaveAs(directory_path + filename);
}
As gaffleck said it would be nice if GDI+ had thrown more informative exception.
I had the same generic exception, but then I gave write permission to the IIS on parallel plesk file manager. if you are on windows server, make sure to give write permission to IIS user which was IIS_IUSR in my server
also make sure that the folder you are trying to save is correct as mentioned in above comments

How to check if file exists in a Windows Store App?

Is there any other way of checking whether a file exists in a Windows Store app?
try
{
var file = await ApplicationData.Current.LocalFolder.GetFileAsync("Test.xml");
//no exception means file exists
}
catch (FileNotFoundException ex)
{
//find out through exception
}
According to the accepted answer in this post, there is no other way at the moment. However, the File IO team is considering changing the the api so that it returns null instead of throwing an exception.
Quote from the linked post:
Currently the only way to check if a file exists is to catch the
FileNotFoundException. As has been pointed out having an explicit
check and the opening is a race condition and as such I don't expect
there to be any file exists API's added. I believe the File IO team
(I'm not on that team so I don't know for sure but this is what I've
heard) is considering having this API return null instead of throwing
if the file doesn't exist.
This may be old, but it looks like they've changed how they want you to approach this.
You're supposed to attempt to make the file, then back down if the file already exists. Here is the documentation on it. I'm updating this because this was the first result on my Google search for this problem.
So, in my case I want to open a file, or create it if it doesn't exist. What I do is create a file, and open it if it already exists. Like so:
save = await dir.CreateFileAsync(myFile, CreationCollisionOption.OpenIfExists);
I stumbled on to this blog post by Shashank Yerramilli which provides a much better answer.
I have tested this for windows phone 8 and it works. Haven't tested it on windows store though
I am copying the answer here
For windows RT app:
public async Task<bool> isFilePresent(string fileName)
{
var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
return item != null;
}
For Windows Phone 8
public bool IsFilePresent(string fileName)
{
return System.IO.File.Exists(string.Format(#"{0}\{1}", ApplicationData.Current.LocalFolder.Path, fileName);
}
Check if a file exists in Windows Phone 8 and WinRT without exception
You can use the old Win32 call like this to test if directory exist or not:
GetFileAttributesExW(path, GetFileExInfoStandard, &info);
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? false: true;
It works in Desktop and Metro apps:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946%28v=vs.85%29.aspx
Microsoft has added a new function to StorageFile in Windows 8.1 to allow user engineers to determine if a file can be accessed: IsAvailable
The other means to check is by getting files in local folder
var collection = ApplicationData.Current.LocalFolder.GetFilesAsync()
Using this method and then iterating over all the elements in the collection and check for its availability.
I tried to write my own using old tricks:
GetFileAttributesEx() always seems to end up with ERROR_ACCESS_DENIED if file selected via FileOpenPicker;
Ditto for FindFirstFileEx();
_stat() always ends up with ENOENT when file selected via FileOpenPicker;
CreateFile2() with CREATE_NEW option works -- if file does exist it will fail with INVALID_HANDLE_VALUE return value and ERROR_FILE_EXISTS last error; if file does not exist you have to remember to delete created file afterwards.
All in all -- you're better of sticking with exception handling method.
8.1 got something like this, I tried it worked.
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.TryGetItemAsync("mytext.txt") as IStorageFile;
if (file == null)
{
//do what you want
}
else
{
//do what you want
}
http://marcominerva.wordpress.com/2013/11/19/how-to-check-if-a-file-exists-in-a-windows-8-1-store-apps-no-more-exception-handling/
Dim myPath As StorageFolder
If (From i In Await KnownFolders.MusicLibrary.GetFoldersAsync() Where i.Name = "PodBong").Count = 1 Then
myPath = Await KnownFolders.MusicLibrary.GetFolderAsync("PodBong")
Else
myPath = Await KnownFolders.MusicLibrary.CreateFolderAsync("PodBong")
End If
The documentation for TryGetItemAsync says, "This example shows how to checkfor the existence of a file." It seems that this API is officially intended to serve that purpose.

How to properly use File.Exists in windows application

I have a windows application with an "images" folder. I need to check if an image exists, which it will, during runtime. The below code is what I have but it always returns false.
if ( File.Exists("images/" + item.tool_image) )
{
Image img;
img = Image.FromFile("images/" + item.tool_image);
titem.Image = img;
}
Whats the problem or the proper way to do this.
If the file you're looking for doesn't exist in the working directory of your application, call File.Exists with a fully-qualified path:
if (File.Exists(#"C:\images\" + item.tool_image))
{ ... }
Of course, verify that a file actually exists at that location.
You'll find life easier if you use the tools provided by the Path class:
if (File.Exists(Path.Combine(#"C:\images", item.tool_image)))
{ ... }
The path is wrong try to change it to
string basePath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
string imageFileName = System.IO.Path.Combine(basePath, "Images",item.tool_image);
if ( File.Exists(imageFileName) )
{
Image img;
img = Image.FromFile(imageFileName);
titem.Image = img;
}
How to properly use File.Exists in windows application?
You don't!
It's almost never appropriate to check if a file exists before trying to open. There are other things at work here: permissions, locking, sharing, time.
Instead, the correct way to do this is to try to open the file, whether it exists or not, and then catch the exception if your attempt to open the file fails. You have to be able to handle this exception anyway, even after performing the File.Exists() check. This makes your initial File.Exists() check not only redundant to your code, but wasteful, because it causes an extra trip out to the file system... and there's not much you can do in programming that's slower than going to the file system.
it is looking from the location where the code is currently running, also the '/' is the wrong direction. also, you are defining the path in multiple places, which can lead to problems later.
var path = string.Format(#"c:\somewhere\images\{0}", item.tool_image);
if (File.Exists(path))
{
Image img;
img = Image.FromFile(path);
titem.Image = img;
}
it's up to you to set the variable path , but in all likelihood, in your code example the location you expect isn't being checked.
The way you're calling it, you are looking for a file of whatever is in the string item.tool_image inside the images folder. Note that this images folder is located inside whatever directory contains your executable.
For instance, i just called File.Exists("images/image.jpg") and it worked.
As everyone has mentioned, use the fully qualified path. I also make heavy use of the Path.Combine, so I don't have to worry about missing a slash or two when I'm combining directories. The current executing directory is also useful...
File.Exists(Path.Combine(Environment.CurrentDirectory, "Images", item.tool_image));

Categories

Resources