I have the following method that validates if certain file exist in the a zipped file.
The method might get a zipped file or not from IFormFile.
private static bool FileExistsInZip(IFormFile uploadedFile, string fileName)
{
using ZipArchive archive = new ZipArchive(uploadedFile.OpenReadStream(), ZipArchiveMode.Read);
return archive.Entries.Any(entry => entry.Name.Equals(fileName, StringComparison.OrdinalIgnoreCase));
}
So in the above method, uploaded file could be zip file or just text file or an image. I was wondering if ZipArchive will return false in this case but it throws ArgumentOutOfRange exception when trying to open file type that is not in Zip format. For example a 4 byte txt file.
What would be the right approach to handle this kind of scenario ?
The typical solution when there is an exception is to catch it and handle it somehow.
However, if you want to test if a file is a zip file you can instead check the header. For zip files this should be 0x04034b50. So something like:
using var br = new BinaryReader(uploadedFile.OpenReadStream());
if(br.ReadUint32 == 0x04034b50){
//is zip file
}
This will only check if the header has the correct magic numbers, it will not tell if the actual file is corrupted, for that you might need to read the entire file, including any entries, and catch any exception that occur. If you want to know the specific file type there are lists of magic numbers for different file formats.
Related
I'm using ZipFile.Open() to create an archive, then adding entries using CreateEntryFromFile(). The resulting file is invalid according to Windows. 7-zip can open the file, but only part of the files are listed.
The code looks like this:
using (ZipArchive archive = ZipFile.Open(archivePath, ZipArchiveMode.Create))
{
while (reader.Read())
{
object myValue = reader.GetValue(0);
string objectId = myValue.ToString();
string objectPath = Path.Combine(myPath, objectId);
string[] files = Directory.GetFiles(objectPath);
if (files.Length > 0)
{
archive.CreateEntryFromFile(files[0], Path.GetFileName(files[0]));
}
}
}
As you can see, I do dispose of the ZipArchive when I'm done, and unlike every other question about this problem, I don't use any streams, so there's nothing to flush.
Anyone know what's wrong?
It could be possible that the file being added to the archive is being used by another process and cannot be accessed. To avoid this, you can try wrapping the CreateEntryFromFile method in a try-catch block and handle the IOException that could be thrown if the file is in use. You can also try closing any streams or file handles that may have been opened on the file before adding it to the archive.
I am using C# in Microsoft Visual Studio 2012, I am working on the following code:
string source = "d:\\source.txt";
string newFile = "d:\\newFile.txt";
if(!File.Exists(newFile))
{
File.Create(newFile);
string content = File.ReadAllText(source);
File.AppendAllText(newFile,content);
}
This code successfully creates the File but when it compiles the File.AppendAllText(newFile,content) it generates the error:
the process cannot access the file "d:\newFile.txt" because it is being used by another process.
Why would this be?
The File.Create method returns a FileStream object. This is holding the file open for write. Until that object is closed the file cannot be written to. The best way to fix this is to simply close the returned file
File.Create(newFile).Close();
This code is essentially copying the contents of an existing file to a new one. There is already an API available that does exactly that: File.Copy. Your code could be simplified to the following
try {
File.Copy(source, newFile);
} catch (Exception) {
// File already exists or write can't occur
}
you don't need to create file , AppendAllText create if not exist, you get exception because File.Create return open file stream and then you try to access same file again. you need to properly close that stream before access the same file.
string source = "d:\\source.txt";
string newFile = "d:\\newFile.txt";
if(!File.Exists(newFile))
{
File.AppendAllText(newFile,File.ReadAllText(source););
}
File.AppendAllText:
Opens a file, appends the specified string to the file, and then
closes the file. If the file does not exist, this method creates a
file, writes the specified string to the file, then closes the file.
but you can simply do your task by one line
File.Copy(source , newFile , false);
I use to store document/file in byte[] in database, and I want user can view/run that file from my application.
You need to know the file extension for the file you're writing, so the OS can run the default program based on the extension. The code would be something like this:
byte[] bytes = GetYourBytesFromDataBase();
string extension = GetYourFileExtension(); //.doc for example
string path = Path.GetTempFileName() + extension;
try
{
using(BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
writer.Write(yourBytes);
}
// open it with default application based in the
// file extension
Process p = System.Diagnostics.Process.Start(path);
p.Wait();
}
finally
{
//clean the tmp file
File.Delete(path);
}
You will need to store the file extension in the database too. If you don't have the file extension the problem becomes very difficult as you cannot rely on the operating system to work out which program to launch to handle the file.
You can use the following pattern:
Load data from database and save to file using the original file extension.
Start a new System.Diagnostics.Process that points to the saved file path.
As you have saved the file with the original file extension, the OS will look for a program that is registered for the extension to open the file.
As chibacity and Daniel suggest, storing the file extension in the db, and agreed -- storing the file extension, or at least some indicator that tells you the file type, is a good idea.
If these files are of a format of your own creation then you might also want to store information about which version of the file format the data is stored in. During development file formats are prone to changing, and if you don't remember which version you used to store the data then you have a hard job recovering the information.
The same problems are faced in object persistence generally.
HI
I Try Upload a file in Silver-Light. for doing this I use System.IO.File to read file bytes and then send the data to service to insert that data as file data in Database.
(Blow Code)
byte[] data;
OpenFileDialog open = new OpenFileDialog();
open.Filter = "Excel Files (*.xlsx)|*.xlsx";
if (open.ShowDialog()==true)
{
open.File.OpenRead();
data=System.IO.File.ReadAllBytes(open.File.FullName);
//---- send for service ---Service.savefileindatabase(data);
}
so when use this code in line which include "ReadAllBytes" exception throw by VS, this is Exception Detail:
"File operation not permitted. Access to path '' is denied."
(for more info that file which i selected was in local Drive)
So What do I do?
In Silverlight there are far more restrictions than in usual wpf programming. The files you might upload may be only in specific directories and some methods are not available like File.FullName. Only a manually selected file might be uploaded. Your starting code is OK. But in silverlight you do not have access to paths (only to the name).
There are some OpenText, OpenRead methods which allow you to get a stream from the selected file. From that point you'll be able to do what you want with the data coming from the stream.
if (open.ShowDialog())
{
using (StreamReader reader = open.SelectedFile.OpenRead())
{
...
}
}
I have a string with a C# program that I want to write to a file and always overwrite the existing content. If the file isn't there, the program should create a new file instead of throwing an exception.
System.IO.File.WriteAllText (#"D:\path.txt", contents);
If the file exists, this overwrites it.
If the file does not exist, this creates it.
Please make sure you have appropriate privileges to write at the location, otherwise you will get an exception.
Use the File.WriteAllText method. It creates the file if it doesn't exist and overwrites it if it exists.
Generally, FileMode.Create is what you're looking for.
Use the file mode enum to change the File.Open behavior. This works for binary content as well as text.
Since FileMode.Open and FileMode.OpenOrCreate load the existing content to the file stream, if you want to replace the file completely you need to first clear the existing content, if any, before writing to the stream. FileMode.Truncate performs this step automatically
// OriginalFile:
oooooooooooooooooooooooooooooo
// NewFile:
----------------
// Write to file stream with FileMode.Open:
----------------oooooooooooooo
var exists = File.Exists(path);
var fileMode = exists
? FileMode.Truncate // overwrites all of the content of an existing file
: FileMode.CreateNew // creates a new file
using (var destinationStream = File.Open(path, fileMode)
{
await newContentStream.CopyToAsync(destinationStream);
}
FileMode Enum
If your code doesn't require the file to be truncated first, you can use the FileMode.OpenOrCreate to open the filestream, which will create the file if it doesn't exist or open it if it does. You can use the stream to point at the front and start overwriting the existing file?
I'm assuming your using a streams here, there are other ways to write a file.