Stream is not a valid resource file - c#

I am uploading a file to Api and trying to read the resource key and values. I am getting below exception when I try to read the file.
System.ArgumentException: Stream is not a valid resource file.
at System.Resources.ResourceReader._ReadResources()
at System.Resources.ResourceReader.ReadResources()
at System.Resources.ResourceReader..ctor(String fileName)
Below is the code which I tried.
[HttpPost]
public async Task<ActionResult> Post(IFormFileCollection files)
{
try
{
files = this.Request.Form.Files;
var tempFolder = Path.GetTempPath();
foreach (var formFile in files)
{
string fileName = ContentDispositionHeaderValue.Parse(formFile.ContentDisposition).FileName.Trim('"');
string filePath = Path.Combine(tempFolder, fileName);
if (formFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream).ConfigureAwait(false);
}
var resReader = new ResourceReader(#filePath); // Throwing an exception.
}
}
}
catch (Exception ex)
{
throw;
}
return this.Ok("Success.");
}
Below is the request Uri and file.
Am I missing any configuration?

ResourceReader reads binary resource files (.resources) not text resource flies (.resx). At compile time the text resource files are compiled to their binary equivalent.
Refer to this link https://learn.microsoft.com/en-us/dotnet/core/extensions/work-with-resx-files-programmatically; on how to work with .resx files programmatically.
If you have the file physically and the definition of the resource in your .resx file, just rebuild your solution and the problem will be solved.

Looks like in the .NET 4.8 Framework the ResourceReader reads .resource files and the ResXResourceReader reads .resx files now.
This was different in previous versions of .Net where you could just use the ResourceReader.
To use the ResxResourceReader, add a reference to System.Windows.Forms to your project, and change the code to use the ResXResourceReader instead of the ResourceReader.
Source: https://learn.microsoft.com/en-us/dotnet/api/system.resources.resxresourcereader?view=netframework-4.8

Related

XML file from ZIP Archive is incomplete in C#

I've work with large XML Files (~1000000 lines, 34mb) that are stored in a ZIP archive. The XML file is used at runtime to store and load app settings and measurements. The gets loadeted with this function:
public static void LoadFile(string path, string name)
{
using (var file = File.OpenRead(path))
{
using (var zip = new ZipArchive(file, ZipArchiveMode.Read))
{
var foundConfigurationFile = zip.Entries.First(x => x.FullName == ConfigurationFileName);
using (var stream = new StreamReader(foundConfigurationFile.Open()))
{
var xmlSerializer = new XmlSerializer(typeof(ProjectConfiguration));
var newObject = xmlSerializer.Deserialize(stream);
CurrentConfiguration = null;
CurrentConfiguration = newObject as ProjectConfiguration;
AddRecentFiles(name, path);
}
}
}
}
This works for most of the time.
However, some files don't get read to the end and i get an error that the file contains non valid XML. I used
foundConfigurationFile.ExtractToFile();
and fount that the readed file stops at line ~800000. But this only happens inside this code. When i open the file via editor everything is there.
It looks like the zip doesnt get loaded correctly, or for that matter, completly.
Am i running in some limitations? Or is there an error in my code i don't find?
The file is saved via:
using (var file = File.OpenWrite(Path.Combine(dirInfo.ToString(), fileName.ToString()) + ".pwe"))
{
var zip = new ZipArchive(file, ZipArchiveMode.Create);
var configurationEntry = zip.CreateEntry(ConfigurationFileName, CompressionLevel.Optimal);
var stream = configurationEntry.Open();
var xmlSerializer = new XmlSerializer(typeof(ProjectConfiguration));
xmlSerializer.Serialize(stream, CurrentConfiguration);
stream.Close();
zip.Dispose();
}
Update:
The problem was the File.OpenWrite() method.
If you try to override a file with this method it will result in a mix between the old file and the new file, if the new file is shorter than the old file.
File.OpenWrite() doenst truncate the old file first as stated in the docs
In order to do it correctly it was neccesary to use the File.Create() method. Because this method truncates the old file first.

Attach file to Winform and copy the file to local while running exe c#

Is it possible to attach a text file resource to my Winform exe. So when I run the "Form.exe" in another computer then it copy the text file to a specified folder. Please suggest a method to achieve the same. Thanks
If the resource name is a string:
var assembly = Assembly.GetExecutingAssembly();
using (var stream = assembly.GetManifestResourceStream(resourceName))
using (var reader = new StreamReader(stream))
{
string text = reader.ReadToEnd();
File.WriteAllText(fileName, text);
}
else:
File.WriteAllText(fileName, Properties.Resources.TextFile1);
And also make sure that you have set the Build Action of the resource file to "Embedded Resource".
First you need to add your file as a resource in your project.
This explains what to do
Then select your file and in the properties change the "Build Action" to "Embedded Resource". This will now embed your file in your output (.exe).
To extract the file you need to do the following;
String myProject = "Name of your project";
String file = "Name of your file to extract";
String outputPath = #"c:\path\to\your\output";
using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(myProject + ".Resources." + file))
{
using (System.IO.FileStream fileStream = new System.IO.FileStream(outputPath + "\\" + file, System.IO.FileMode.Create))
{
for (int i = 0; i < stream.Length; i++)
{
fileStream.WriteByte((byte)stream.ReadByte());
}
fileStream.Close();
}
}
Ideally you should check that the file does not already exist before you do this. Don't forget also to catch exceptions. Which can be very common when dealing with the file system.
Add the text file to your project resources
Properties -> Resources -> Add Resource
Read the data from the resource using
var text = Properties.Resources.textFile;
Write to the file with
File.WriteAllText(#"C:\test\testOut.txt", text);

OutOfMemory exception when trying to download multiple files as a Zip file using Ionic.Zip dll

This is my working code that I used to download multiple files as a zip file using Ionic.Zip dll. File contents is stored in a SQL database. This program works if I try to download 1-2 files at a time, but throws an OutOfMemory exception if I try to download multiple files as some of the files may very large.
Exception occurs when it's trying to write in to outputStream.
How can I improve this code to download multiple files or is there a better way to download multiple files one by one rather than zipping them to a one large file?
Code:
public ActionResult DownloadMultipleFiles()
{
string connectionString = "MY DB CONNECTIOBN STRING";
List<Document> documents = new List<Document>();
var query = "MY LIST OF FILES - FILE METADA DATA LIKE FILEID, FILENAME";
documents = query.Query<Document>(connectionString1).ToList();
List<Document> DOCS = documents.GetRange(0, 50); // 50 FILES
Response.Clear();
var outputStream = new MemoryStream();
using (var zip = new ZipFile())
{
foreach (var doc in DOCS)
{
Stream stream = new MemoryStream();
byte[] content = GetFileContent(doc.FileContentId); // This method returns file content
stream.Write(content, 0, content.Length);
zip.UseZip64WhenSaving = Zip64Option.AsNecessary // edited
zip.AddEntry(doc.FileName, content);
}
zip.Save(outputStream);
}
return File(outputStream, "application/zip", "allFiles.zip");
}
Download the files to disc instead of to memory, then use Ionic to zip them from disc. This means you don't need to have all the files in memory at once.

C# - Getting file version of embedded resource files

I have several files that I have as embedded resources of a WPF application. I would like to be able to find the file versions of these resources without writing them out to a file first. Is this possible?
I'm not sure if this will help, but after searching for how to package my embedded resource .DLLs into one .exe, I ran into the code from below. You can use Assembly to gather an embedded resources, such as a .DLL's File Version. In short, using Assembly.Load(byte[]), you can figure out the file version.
var assemblies = new Dictionary<string, Assembly>();
var executingAssembly = Assembly.GetExecutingAssembly();
var resources = executingAssembly.GetManifestResourceNames().Where(n => n.EndsWith(".dll"));
foreach (string resource in resources)
{
using (var stream = executingAssembly.GetManifestResourceStream(resource))
{
if (stream == null)
continue;
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
try
{
//After Assembly.Load is called, you can find the File Version
assemblies.Add(resource, Assembly.Load(bytes));
}
catch (Exception ex)
{
System.Diagnostics.Debug.Print(string.Format("Failed to load: {0}, Exception: {1}", resource, ex.Message));
}
}
}
Some source can be found here.
This might help too.

Reading embedded XML file c#

How can I read from an embedded XML file - an XML file that is part of a c# project?
I've added a XML file to my project and I want to read from it. I want the XML file to compile with the project because I don't want that it will be a resource which the user can see.
Any idea?
Make sure the XML file is part of your .csproj project. (If you can see it in the solution explorer, you're good.)
Set the "Build Action" property for the XML file to "Embedded Resource".
Use the following code to retrieve the file contents at runtime:
public string GetResourceTextFile(string filename)
{
string result = string.Empty;
using (Stream stream = this.GetType().Assembly.
GetManifestResourceStream("assembly.folder."+filename))
{
using (StreamReader sr = new StreamReader(stream))
{
result = sr.ReadToEnd();
}
}
return result;
}
Whenever you want to read the file contents, just use
string fileContents = GetResourceTextFile("myXmlDoc.xml");
Note that "assembly.folder" should be replaced with the project name and folder containing the resource file.
Update
Actually, assembly.folder should be replaced by the namespace in which a class created in the same folder as the XML file would have by default. This is typically defaultNamespace.folder0.folder1.folder2......
You can also add the XML file as a Resource and then address its contents with Resources.YourXMLFilesResourceName (as a string, i.e. using a StringReader).
Set the Build Action to Embedded Resource, then write the following:
using (Stream stream = typeof(MyClass).Assembly.GetManifestResourceStream("MyNameSpace.Something.xml")) {
//Read the stream
}
You can use Reflector (free from http://www.red-gate.com/products/reflector/) to find the path to the embedded XML file.
Then, it's just a matter of
Assembly a = typeof(Assembly.Namespace.Class).Assembly;
Stream s = a.GetManifestResourceStream("Assembly.Namespace.Path.To.File.xml");
XmlDocument mappingFile = new XmlDocument();
mappingFile.Load(s);
s.Close();
Add the file to the project.
Set the "Build Action" property to "Embedded Resource".
Access it this way:
GetType().Module.Assembly.GetManifestResourceStream("namespace.folder.file.ext")
Notice that the resource name string is the name of the file,
including extension, preceded by the default namespace of the project.
If the resource is inside a folder, you also have to include it in the
string.
(from http://www.dotnet247.com/247reference/msgs/1/5704.aspx, but I used it pesonally)
#3Dave really helped (up vote given), however my resource helper was in a different assembly so I did the below
public string GetResourceFileText(string filename, string assemblyName)
{
string result = string.Empty;
using (Stream stream =
System.Reflection.Assembly.Load(assemblyName).GetManifestResourceStream($"{assemblyName}.{filename}"))
{
using (StreamReader sr = new StreamReader(stream))
{
result = sr.ReadToEnd();
}
}
return result;
}
Called by
GetResourceFileText("YourFileNameHere.ext", Assembly.GetExecutingAssembly().GetName().Name);

Categories