How to open up a zip file from MemoryStream - c#

I am using DotNetZip.
What I need to do is to open up a zip files with files from the server.
The user can then grab the files and store it locally on their machine.
What I did before was the following:
string path = "Q:\\ZipFiles\\zip" + npnum + ".zip";
zip.Save(path);
Process.Start(path);
Note that Q: is a drive on the server. With Process.Start, it simply open up the zip file so that the user can access all the files. I like to do the same but not store the file on disk but show it from memory.
Now, instead of storing the zip file on the server, I like to open it up with MemoryStream
I have the following but does not seem to work
var ms = new MemoryStream();
zip.Save(ms);
but not sure how to proceed further in terms of opening up the zip file from a memory stream so that the user can access all the files

Here is a live piece of code (copied verbatim) which I wrote to download a series of blog posts as a zipped csv file. It's live and it works.
public ActionResult L2CSV()
{
var posts = _dataItemService.SelectStuff();
string csv = CSV.IEnumerableToCSV(posts);
// These first two lines simply get our required data as a long csv string
var fileData = Zip.CreateZip("LogPosts.csv", System.Text.Encoding.UTF8.GetBytes(csv));
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "LogPosts.zip",
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(fileData, "application/octet-stream");
}

You can use:
zip.Save(ms);
// Set read point to beginning of stream
ms.Position = 0;
ZipFile newZip = ZipFile.Read(ms);

See the documentation for Create a zip using content obtained from a stream.
using (ZipFile zip = new ZipFile())
{
ZipEntry e= zip.AddEntry("Content-From-Stream.bin", "basedirectory", StreamToRead);
e.Comment = "The content for entry in the zip file was obtained from a stream";
zip.AddFile("Readme.txt");
zip.Save(zipFileToCreate);
}
After saving it, you can then open it up as normal.

Related

Xamarin android data saving to json file

I need to save the file when method OnDestroy is called and load same file when method OnCreate is called. At this time I can read json file easily from Assets (this works fine)
StreamReader reader = new StreamReader(Assets.Open("reiksmes.json"));
string JSONstring = reader.ReadToEnd();
Daiktai myList = JsonConvert.DeserializeObject<Daiktai>(JSONstring);
items.Add(myList);
, but I have some problems when I try to save(write) Daiktai class data to the same file I opened above. I tried:
string data = JsonConvert.SerializeObject(items);
File.WriteAllText("Assets\\reiksmes.json", data);
with this try I get error System.UnauthorizedAccessException: Access to the path "/Assets
eiksmes.json" is denied.
also tried:
string data = JsonConvert.SerializeObject(items);
StreamWriter writer = new StreamWriter(Assets.Open("reiksmes.json"));
writer.WriteLine(data);
and with this try I get error System.ArgumentException: Stream was not writable.
Summary:
I think I chose bad directory(Assets), I need to save and load data (json format). So where do I need to save them and how(give example)?
You can't save anything to assets. You can just read from it. You have to save the file to a different folder.
var fileName = "reiksmes.json";
string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); // Documents folder
var path = Path.Combine(documentsPath, fileName);
Console.WriteLine(path);
if (!File.Exists(path))
{
var s = AssetManager.Open(fileName);
// create a write stream
FileStream writeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
// write to the stream
ReadWriteStream(s, writeStream);
}

zip does'n show me any issue

Here i have several images and i need to zip those images and need to download it..In here i use Ionzip.The problem is that zip is not working.It doen't shows me any error.
MyCode
public bool DownloadImgs()
{
string Path = HttpContext.Current.Server.MapPath("../Content/images/QImages");
string zippath = HttpContext.Current.Server.MapPath("../Content/images/QImages/zipped/");
string[] filenames = System.IO.Directory.GetFiles(Path, "*.jpg", SearchOption.AllDirectories);//It returns all the paths of the images.
using (ZipFile zip = new ZipFile())
{
foreach (String filename in filenames)
{
ZipEntry e = zip.AddFile(filename, "");
}
zip.Save(zippath);//In here i need to download the zipped file.not to save
}
}
PS: This application is built using MVC framework
You should write the resulting zip to the Response stream.
From a MVC controller:
return this.File(zippath, "application/zip");
From an ASP.NET handler or page:
Response.TransmitFile(zippath);
Another option is to directly save the zip file to the response stream, which will optimize your disk usage.
You can save your zip file straight to the response outputstream:
zipFile.Save(Response.OutputStream);

mvc3 c# streamreader file not reading

I have a file, which the users browse and hit the upload button, i save the file on the server, appdata/uploads in the application directory. then i try to read it using stream reader and then parse it. on my local development enviornment it works fine, but when i deploy it on a server it does not work at all. any suggestions?? thank you
//Save LoadList File:
DateTime uploadDate = DateTime.Now;
string destinationPath = string.Format("{0}\\{1}\\{2}\\{3}\\", Server.MapPath("~/App_Data/uploads"), uploadDate.ToString("yyyy"), uploadDate.ToString("MMM"), uploadDate.ToString("dd"));
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
string storedFileName = string.Format("{0}{1}.json", destinationPath, System.Guid.NewGuid());
file.ElementAt(0).SaveAs(storedFileName);
//FileImport is a static class
var Pair = FileImport.CyclesCompleted(storedFileName);
private static string LoadTextFromFile(string fileName)
{
StreamReader streamReader = new StreamReader(fileName);
string text = streamReader.ReadToEnd();
streamReader.Close();
return text;
}
Saving file on server ususlly results in permission errors since most accounts can't write to default location on server. You may get away with using Path.GetTempFileName, but even in this case some accounts (i.e. account that requests run for "anonymous user") will not have permissions to read/write to that location.
If you simply need to parse uploaded file you can copy stream to MemoryStream and create StreamReader over this memory stream. You may be able to use Stream for uploaded file directly, but it will not support seaking (may work as you are using StreamReader which does not seek).

How to read data from a zip file without having to unzip the entire file

Is there anyway in .Net (C#) to extract data from a zip file without decompressing the complete file?
I possibly want to extract data (file) from the start of a zip file if the compression algorithm compress the file used was in a deterministic order.
With .Net Framework 4.5 (using ZipArchive):
using (ZipArchive zip = ZipFile.Open(zipfile, ZipArchiveMode.Read))
foreach (ZipArchiveEntry entry in zip.Entries)
if(entry.Name == "myfile")
entry.ExtractToFile("myfile");
Find "myfile" in zipfile and extract it.
DotNetZip is your friend here.
As easy as:
using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
ZipEntry e = zip["MyReport.doc"];
e.Extract(OutputStream);
}
(you can also extract to a file or other destinations).
Reading the zip file's table of contents is as easy as:
using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
foreach (ZipEntry e in zip)
{
if (header)
{
System.Console.WriteLine("Zipfile: {0}", zip.Name);
if ((zip.Comment != null) && (zip.Comment != ""))
System.Console.WriteLine("Comment: {0}", zip.Comment);
System.Console.WriteLine("\n{1,-22} {2,8} {3,5} {4,8} {5,3} {0}",
"Filename", "Modified", "Size", "Ratio", "Packed", "pw?");
System.Console.WriteLine(new System.String('-', 72));
header = false;
}
System.Console.WriteLine("{1,-22} {2,8} {3,5:F0}% {4,8} {5,3} {0}",
e.FileName,
e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
e.UncompressedSize,
e.CompressionRatio,
e.CompressedSize,
(e.UsesEncryption) ? "Y" : "N");
}
}
Edited To Note: DotNetZip used to live at Codeplex. Codeplex has been shut down. The old archive is still available at Codeplex. It looks like the code has migrated to Github:
https://github.com/DinoChiesa/DotNetZip. Looks to be the original author's repo.
https://github.com/haf/DotNetZip.Semverd. This looks to be the currently maintained version. It's also packaged up an available via Nuget at https://www.nuget.org/packages/DotNetZip/
Something like this will list and extract the files one by one, if you want to use SharpZipLib:
var zip = new ZipInputStream(File.OpenRead(#"C:\Users\Javi\Desktop\myzip.zip"));
var filestream = new FileStream(#"C:\Users\Javi\Desktop\myzip.zip", FileMode.Open, FileAccess.Read);
ZipFile zipfile = new ZipFile(filestream);
ZipEntry item;
while ((item = zip.GetNextEntry()) != null)
{
Console.WriteLine(item.Name);
using (StreamReader s = new StreamReader(zipfile.GetInputStream(item)))
{
// stream with the file
Console.WriteLine(s.ReadToEnd());
}
}
Based on this example: content inside zip file
Here is how a UTF8 text file can be read from a zip archive into a string variable (.NET Framework 4.5 and up):
string zipFileFullPath = "{{TypeYourZipFileFullPathHere}}";
string targetFileName = "{{TypeYourTargetFileNameHere}}";
string text = new string(
(new System.IO.StreamReader(
System.IO.Compression.ZipFile.OpenRead(zipFileFullPath)
.Entries.Where(x => x.Name.Equals(targetFileName,
StringComparison.InvariantCulture))
.FirstOrDefault()
.Open(), Encoding.UTF8)
.ReadToEnd())
.ToArray());
the following code can read specific file as byte array :
using ZipArchive zipArchive = ZipFile.OpenRead(zipFilePath);
foreach(ZipArchiveEntry zipArchiveEntry in zipArchive.Entries)
{
if(zipArchiveEntry.Name.Equals(fileName,StringComparison.OrdinalIgnoreCase))
{
Stream stream = zipArchiveEntry.Open();
using MemoryStream memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
}
Zip files have a table of contents. Every zip utility should have the ability to query just the TOC. Or you can use a command line program like 7zip -t to print the table of contents and redirect it to a text file.
In such case you will need to parse zip local header entries. Each file, stored in zip file, has preceding Local File Header entry, which (normally) contains enough information for decompression, Generally, you can make simple parsing of such entries in stream, select needed file, copy header + compressed file data to other file, and call unzip on that part (if you don't want to deal with the whole Zip decompression code or library).

SharpZipLib : Compressing a single file to a single compressed file

I am currently working with SharpZipLib under .NET 2.0 and via this I need to compress a single file to a single compressed archive. In order to do this I am currently using the following:
string tempFilePath = #"C:\Users\Username\AppData\Local\Temp\tmp9AE0.tmp.xml";
string archiveFilePath = #"C:\Archive\Archive_[UTC TIMESTAMP].zip";
FileInfo inFileInfo = new FileInfo(tempFilePath);
ICSharpCode.SharpZipLib.Zip.FastZip fZip = new ICSharpCode.SharpZipLib.Zip.FastZip();
fZip.CreateZip(archiveFilePath, inFileInfo.Directory.FullName, false, inFileInfo.Name);
This works exactly (ish) as it should, however while testing I have encountered a minor gotcha. Lets say that my temp directory (i.e. the directory that contains the uncompressed input file) contains the following files:
tmp9AE0.tmp.xml //The input file I want to compress
xxx_tmp9AE0.tmp.xml // Some other file
yyy_tmp9AE0.tmp.xml // Some other file
wibble.dat // Some other file
When I run the compression all the .xml files are included in the compressed archive. The reason for this is because of the final fileFilter parameter passed to the CreateZip method. Under the hood SharpZipLib is performing a pattern match and this also picks up the files prefixed with xxx_ and yyy_. I assume it would also pick up anything postfixed as well.
So the question is, how can I compress a single file with SharpZipLib? Then again maybe the question is how can I format that fileFilter so that the match can only ever pick up the file I want to compress and nothing else.
As an aside, is there any reason as to why System.IO.Compression not include a ZipStream class? (It only supports GZipStream)
EDIT : Solution (Derived from accepted answer from Hans Passant)
This is the compression method I implemented:
private static void CompressFile(string inputPath, string outputPath)
{
FileInfo outFileInfo = new FileInfo(outputPath);
FileInfo inFileInfo = new FileInfo(inputPath);
// Create the output directory if it does not exist
if (!Directory.Exists(outFileInfo.Directory.FullName))
{
Directory.CreateDirectory(outFileInfo.Directory.FullName);
}
// Compress
using (FileStream fsOut = File.Create(outputPath))
{
using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(fsOut))
{
zipStream.SetLevel(3);
ICSharpCode.SharpZipLib.Zip.ZipEntry newEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(inFileInfo.Name);
newEntry.DateTime = DateTime.UtcNow;
zipStream.PutNextEntry(newEntry);
byte[] buffer = new byte[4096];
using (FileStream streamReader = File.OpenRead(inputPath))
{
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(streamReader, zipStream, buffer);
}
zipStream.CloseEntry();
zipStream.IsStreamOwner = true;
zipStream.Close();
}
}
}
This is an XY problem, just don't use FastZip. Follow the first example on this web page to avoid accidents.

Categories

Resources