File replace in HttpPostedFileBase MVC3 - asp.net-mvc-3

If the file is uploading with the name already in the specified path, it is showing error. I want to replace with the new file. I have placed the error and the code. Please help to replace the existing image.
Error: The process cannot access the file '' because it is being used by another process.
Code:
[HttpPost]
public ActionResult MyUpload(HttpPostedFileBase file)
{
string filePath = string.Empty;
string path = "C:\\";
string filePath = string.Empty;
try
{
if (file != null && file.ContentLength > 0)
{
filePath = path + file.FileName;
file.SaveAs(filePath);
file.InputStream.Dispose();
GC.Collect();
// other operations, where can occur an exception
// (because the uploaded file can have a bad content etc.)
}
}
catch (Exception e)
{
}
}

Based upon what you posted, I would suggest the following:
[HttpPost]
public ActionResult Foo(HttpPostedFileBase file)
{
var path = #"C:\";
var filename = file.FileName;
file.SaveAs(System.IO.Path.Combine(path, filename));
// do stuff here.
return RedirectToAction("Index");
}

I had this very same issue. I had a sub-folder called "files" where I uploaded files using file.SaveAs() ('file' being of type 'HttpPostedFileBase' [using MVC]). After some local investigation and online research, it turns out that an IIS worker thread/process was locking my file. At first I thought {HttpPostedFileBase}.SaveAs() was somehow locking my file. I even tried to (first) close, and then dispose the {HttpPostedFileBase}.InputStream, and that also didn't help. In the end, it wasn't even related to the file upload process at all. After uploading the file (a PDF), I processed it using ITextSharp, but forgot to dispose of the object wrapper (so it was probably sitting in the GC). Because of that, the next file upload failed due to the locked existing file. BTW, I also tried file.InputStream.Dispose(); file.InputStream.Close(); GC.Collect();, but removed them all in the end, and it still works perfectly now. Bottom line, if an IIS Worker process is locking your file, there's probably a good reason - something somewhere in your code you are missing, and it most likely isn't the MVC framework or IIS itself gone rogue. ;) Also, as it turns out, {HttpPostedFileBase}.SaveAs() WILL overwrite files if they exist, so there's no need to delete them first.
One other tip: I read somewhere to watch out who is creating the files based on how your authorization is setup (whether or not you using an IIS process identity, or the logged-in user identity). In some cases, a file may be created by one logged in user, who then becomes the owner, and another file of the same name from a different user may become blocked; might be something to keep in mind in special cases (like intranet based web apps).

Related

Is it safe to use NSFileManager.fileExists(atPath:) for files in iCloud that might not have been downloaded?

I need a 100% fail-safe way to determine if a file name/file URL is available for writing data to disk without accidentally deleting an existing file.
Currently I'm using NSFileManager.fileExists(atPath:), but I'm wondering, what if the parent directory is in iCloud and my file URL points to an existing file in iCloud that hasn't been downloaded to the device yet?
What got me thinking are these two methods of URL:
func checkResourceIsReachable() throws -> Bool
func checkPromisedItemIsReachable() throws -> Bool
There is a distinction between a resource and a promised item. A promised item is defined as:
A promised item is not guaranteed to have its contents in the file
system until you use a file coordinator to perform a coordinated read
on its URL, which causes the contents to be downloaded or otherwise
generated.
Background:
What I'm after is an extension for FileManager that returns the next available, non-existing file name for a given (existing) file URL. For example:
Let's say my existing document is: /documents/Text.txt
The next available file name could be: /documents/Text 2.txt
How can I check that Text 2.txt really doesn't exist locally and in iCloud?
Here's my current approach:
// Safer than: FileManager.default.fileExists(at: url) ?
private func fileExists(at url:URL) throws -> Bool
{
if (try url.resourceValues(forKeys: [.isUbiquitousItemKey])).isUbiquitousItem == true
{
return try url.checkPromisedItemIsReachable()
}
else
{
return try url.checkResourceIsReachable()
}
}

spring-integration-aws dynamic file download

I've a requirement to download a file from S3 based on a message content. In other words, the file to download is previously unknown, I've to search and find it at runtime. S3StreamingMessageSource doesn't seem to be a good fit because:
It relies on polling where as I need to wait for the message.
I can't find any way to create a S3StreamingMessageSource dynamically in the middle of a flow. gateway(IntegrationFlow) looks interesting but what I need is a gateway(Function<Message<?>, IntegrationFlow>) that doesn't exist.
Another candidate is S3MessageHandler but it has no support for listing files which I need for finding the desired file.
I can implement my own message handler using AWS API directly, just wondering if I'm missing something, because this doesn't seem like an unusual requirement. After all, not every app just sits there and keeps polling S3 for new files.
There is S3RemoteFileTemplate with the list() function which you can use in the handle(). Then split() result and call S3MessageHandler for each remote file to download.
Although the last one has functionality to download the whole remote dir.
For anyone coming across this question, this is what I did. The trick is to:
Set filters later, not at construction time. Note that there is no addFilters or getFilters method, so filters can only be set once, and can't be added later. #artem-bilan, this is inconvenient.
Call S3StreamingMessageSource.receive manually.
.handle(String.class, (fileName, h) -> {
if (messageSource instanceof S3StreamingMessageSource) {
S3StreamingMessageSource s3StreamingMessageSource = (S3StreamingMessageSource) messageSource;
ChainFileListFilter<S3ObjectSummary> chainFileListFilter = new ChainFileListFilter<>();
chainFileListFilter.addFilters(
new S3SimplePatternFileListFilter("**/*/*.json.gz"),
new S3PersistentAcceptOnceFileListFilter(metadataStore, ""),
new S3FileListFilter(fileName)
);
s3StreamingMessageSource.setFilter(chainFileListFilter);
return s3StreamingMessageSource.receive();
}
log.warn("Expected: {} but got: {}.",
S3StreamingMessageSource.class.getName(), messageSource.getClass().getName());
return messageSource.receive();
}, spec -> spec
.requiresReply(false) // in case all messages got filtered out
)

Play Framework: Handling dynamic created files (images) in PRODUCTION mode

I'm trying to allow users to upload photos to the server and then view them (all users can view all photos) in production (NOT development). While in development mode everything is simple - I can upload the files to the public folder and then read then from there, in production mode I don't have access to the public folder anymore (as this approach is for static accesses and not dynamic).
So, I have 2 issues:
Upload: currently I can't understand how to save the uploaded photos to a specific folder, without using an absolute path to the location where I want the photos to be saved.
Here is the code for upload (similarly to this guide - https://www.playframework.com/documentation/2.4.x/ScalaFileUpload):
def uploadPhoto = Action(parse.multipartFormData) { request =>
import play.api.mvc.MultipartFormData
import play.api.libs.Files.TemporaryFile
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
try {
val multipartForm: MultipartFormData[TemporaryFile] = request.body
val pathDev: Path = Paths.get("./public/img");
val pathProduction: Path = Paths.get("/...<[full path]>.../public/img");
val imgPath =
if (Files.exists(pathDev)) { pathDev.toString() }
else { pathProduction.toString() }
val newFile = img.get.ref.moveTo(new File(s"$imgPath/$imgName"))
// [HERE I save the path to my DB]
Ok(Json.obj("imgName" -> imgName))
} catch {
case e: Exception =>
BadRequest("unknown error")
}
}
It is unclear to me how to serve the uploaded images back to users that want to see them.
I want to dynamically change the scr in the img html tag to show the relevant image, like so: $("#img").attr("src",'assets/img/1.jpg');
But as the public folder is not available, the images are "not there" (at least until I will "stage" the project and re-run it - https://www.playframework.com/documentation/2.4.x/Assets).
I tried the following approach (https://www.playframework.com/documentation/2.4.x/ScalaStream):
I have added the following line to my conf/routes file:
GET /img/:filename controllers.MyController.getPhoto(filename)
and defined the following function in the controller:
def getPhoto(filename: String) = Action {
Ok.sendFile(new java.io.File("./img/" + filename))
}
But the browser is downloading the file instead of showing it...
These are related:
Handling dynamic created files in play 2
How to serve uploaded files in Play!2 using Scala?
Any assistance will be very appropriated.
Here's how I fix this
ISSUE 1
For upload file path, in play you can define configurations in conf/application.conf file, and you can use different file for production mode, using -Dconfig.file=/path/to/the/file.
So I defined an attribuite called myapp.image.base, in debug mode just set it to "", and in production mode (I created a file called conf/application.prod.conf) , I put an absolute path to it.
So in my code, I always use the following command for file path (it's in Java, but you should find a similar way in Scala for reading configuration)
Play.application().configuration().getString("myapp.image.base")+"img"
ISSUE 2
For serving image
You need to create a router.
First in your routes file, add something like this:
GET /user/images/:name controllers.Application.imageAt(name:String)
And write a simple file reader in action imageAt which return the file in stream. Again my sample is in Java but you should archive the same using Scala
File imageFile = new File(ReportFileHelper.getImagePath());
if (imageFile.exists()) {
//resource type such as image+png, image+jpg
String resourceType = "image+"+imageName.substring(imageName.length()-3);
return ok(new FileInputStream(imageFile)).as(resourceType);
} else {
return notFound(imageFile.getAbsoluteFile());
}
After that, the images is reachable from url /user/images/
Play reads files off the classpath (which includes the assets directory). On the JVM, the classpath is immutable—once started, files added to folders on the classpath will not actually be added to the classpath.
This works in development mode because Play reloads the classpath whenever it detects a change. That same hot-reloading is not enabled in production (for good reason).

Issue with WatchService in java 7

I'm using jdk7's WatchService API for monitoring the folder on file system.I'm sending a new file through
email to that folder, when the file comes into that folder i m triggering the ENTRY_CRATE option. its working fine.
But the issue is its generating two events of ENTRY_CREATE instead of one event which i'm invoking.
BELOW IS THE CODE:
Path dir = Paths.get(/var/mail);
WatchService watcher = dir.getFileSystem().newWatchService();
dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
System.out.println("waiting for new file");
WatchKey watckKey = watcher.take();
List<WatchEvent<?>> events = watckKey.pollEvents();
System.out.println(events.size());
for(WatchEvent<?> event : events){
if(event.kind() == StandardWatchEventKinds.ENTRY_CREATE){
String fileCreated=event.context().toString().trim();
}
}
In the above code I'm gettng the events size as 2.
Can any one please help me in finding out the reason why i'm getting two events.
I am guessing that there might be some temporary files being created in the folder at the same time. Just check what are the name/paths of the file being created.

.NET Settings Relative Path

I am working on an application where I have an images folder relative to my application root. I want to be able to specify this relative path in the Properties -> Settings designer eg. "\Images\". The issue I am running into is in cases where the Environment.CurrentDirectory gets changed via an OpenFileDialog the relative path doesn't resolve to the right location. Is there a way to specifiy in the Settings file a path that will imply to always start from the application directory as opposed to the current directory? I know I can always dynamically concatenate the application path to the front of the relative path, but I would like my Settings property to be able to resolve itself.
As far as I know, there is no built-in functionality that will allow this type of path resolution. Your best option is to dynamically determine the applications executing directory and concatenate to it your images path. You don't want to use Environment.CurrentDirectory specifically for the reasons you mention - the current directory may not always be correct for this situation.
The safest code I've found to find the executing assembly location is this:
public string ExecutingAssemblyPath()
{
Assembly actualAssembly = Assembly.GetEntryAssembly();
if (this.actualAssembly == null)
{
actualAssembly = Assembly.GetCallingAssembly();
}
return actualAssembly.Location;
}
Are you looking for Application.ExecutablePath ? That should tell you where the application's executable is, remove the executable name, and then append your path to it.
2 options:
The code that uses the setting can resolve the setting against the directory of the current executing assembly.
You can create your own type that serializes as a string relative to the executing assembly, and has an accessor for the full path that will resolve against the directory of the current executing assembly.
Code sample:
string absolutePath = Settings.Default.ImagePath;
if(!Path.IsPathRooted(absolutePath))
{
string root = Assembly.GetEntryAssembly().Location;
root = Path.GetDirectoryName(root);
absolutePath = Path.Combine(root, absolutePath);
}
The nice thing about this code is that it allows a fully qualified path, or a relative path, in your settings. If you need the path to be relative to a different assembly, you can change which assembly's location you use - GetExecutingAssembly() will give you the location of the assembly with the code you're running, and GetCallingAssembly() would be good if you go with option 2.
This seem to work in both WinForms and ASP.NET (gives the path to the config file):
new System.IO.FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile).Directory;
For Windows and Console applications, the obvious way is by using:
Application.StartupPath
I suggest you to use Assembly.CodeBase, as shown below:
public static string RealAssemblyFilePath()
{
string dllPath=Assembly.GetExecutingAssembly().CodeBase.Substring(8);
return dllPath;
}
You can try Application.ExecutablePath. But you need to make reference to System.Windows.Forms. This may not be a good idea if you want your class library to steer clear of forms and UI stuff.
You can try the Assembly.GetExecutingAssembly().Location. But if, somehow, you do a "Shadow Copy" before you run your application (like the default NUnit behavior), then this property will return you the shadow copy location, not the real, physical location.
The best way is to implement a function that calls the CodeBase property of Assembly object and chop off the irrelevant portion of the string.
I use the following two methods to help with that:
public static IEnumerable<DirectoryInfo> ParentDirs(this DirectoryInfo dir) {
while (dir != null) {
yield return dir;
dir = dir.Parent;
}
}
public static DirectoryInfo FindDataDir(string relpath, Assembly assembly) {
return new FileInfo((assembly).Location)
.Directory.ParentDirs()
.Select(dir => Path.Combine(dir.FullName + #"\", relpath))
.Where(Directory.Exists)
.Select(path => new DirectoryInfo(path))
.FirstOrDefault();
}
The reason to look at parent dirs to to be easier in use during development when various build scripts end up sticking things in directories like bin\x64\Release\NonsensePath\.

Resources