I have been able to download a zipfile before but then the compression happend on the ASP server. Now we have changed this action to another server (Progress).
At this moment I'm receiving a base64 encoded string which represents a zip file. But how can I convert this string to a zipfile. The code I used before you can find beneath, can I reuse code?
MemoryStream outputStream = new MemoryStream();
outputStream.Seek(0, SeekOrigin.Begin);
using (ZipFile zip = new ZipFile())
{
foreach (string id in idArray)
{
string json = rest.getDocumentInvoice(Convert.ToInt32(id));
byte[] file = json.convertJsonToFile();
zip.AddEntry("invoice" + id + ".pdf", file);
}
zip.Save(outputStream);
}
outputStream.WriteTo(Response.OutputStream);
Response.AppendHeader("content-disposition", "attachment; filename=invoices.zip");
Response.ContentType = "application/zip";
return new FileStreamResult(outputStream, "application/zip");
I have no idea how to convert a string to a zip file. Thanks in advance for your help
Convert the base64 to a byte array by doing:
Convert.fromBase64String(strBase64);
Then I found an article to easily download the zipfile
Download file of any type in Asp.Net MVC using FileResult?
This article suggests:
public FileResult Download()
{
string base64 = getBase64ZIP();
byte[] byteArray = Convert.fromBase64String(base64);
return File(byteArray, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
Use Convert.FromBase64String to get the bytes of the zip file.
string base64String = rest.getDocumentInvoice(Convert.ToInt32(id));
byte[] file = Convert.FromBase64String(base64String);
using(var stream = new MemoryStream(file))
{
zip.AddEntry("invoice" + id + ".pdf", stream);
}
Try this:
HTML:
> <a id='dwnldLnk' download='myzip.zip' style="display:none;" />
> <a ng-click="saveFile()">myzip.zip</a>
Controller:
var dataBase64 = "UEsDBAoAAAAAAORSo04AAAAAAAAAAAAAAAAEABwAc3VtL1VUCQADG7TLXKu/y1x1eAsAAQToAwAABOgDAABQSwMEFAAAAAgAe3WTTkQjafoxAAAAMgAAAAoAHABzdW0vc3VtLmdvVVQJAAM6fLlcha3LXHV4CwABBOgDAAAE6AMAACtITM5OTE9VKC7N5eJKK81LVgguzS3WSNRJUsjMK9EEEdVcnEWpJaVFeQqJ2klctQBQSwMEFAAAAAgAtkqWTksgx3NnAgAAPgQAAAcAHABtYWluLmdvVVQJAAM4Jb1cha3LXHV4CwABBOgDAAAE6AMAAHVTX0/bMBB/Jp/i5KeUlWTjkYmHDKiIxtKJlCGEeHCTS2qR2JntECrEd99dmm6VJvJi2b77/TsnPg7gGG5UgdphCd6A3yAknSxoyU3lB2kRFqbXpfTKaAiTfDED2qIFoxGMhdZYZJTCaG/Vuvd01uwQQdYWsUXtXQSQI47w2XKVXlxBpRqEUrldE7EPym8YyG+Ug8HYZ6gISpalYmrZgNJ00O6EWKylLZWuibfbWlVvPJhBo3Ub1UUMs2In+WKvxe1wR1by+WD6ycaB4ymIOfwiHGY5jT4zVMg1YroVs6+wpe5WbkEbD73DA2h8LbDzJJV0tV2jpC7wwNlfDsrjYQIxay+pXo5OwFSHZSA9NXIvfxvvu7M4HoYhkqPiyNg63huMbyjWLL862anmpjvdoHMU1u9eWYp4vQXZkapCrklrIwce4DikcfikYrCUtq7n4KbpM8zhlP6FtpdI1g8LKDapQSQ5pLmAb0me5nMGuU9X18u7Fdwnt7dJtkqvcljewsUyu0xX6TKj3QKS7AG+p9nlHJAiIx587Sw7IJmK48RynO3+Ke0l8EPhveuwUJUqyJque1kj1OYFreZ30qFtleOxOhJYMkyjWuXH9+T+98VEcRBQzs8M1NKMgoBEGOshDI6E61tBS9V6Xsg//QAvIpgFQRzDD54oqRrk+EYp22tsGhNUvS7Gy1Da2hFo98jJ6fpJaY+2kgW+vc8+OIe34Ijoop904RsdCgYSs+CIIoKzc+p6xvADyLHoUdSGkzlhMyeTM/EE5yBGeXMQ8AkmK1HqjQzJZZT3rQu/zE9nI4rvLf9+Lnj/A1BLAQIeAwoAAAAAAORSo04AAAAAAAAAAAAAAAAEABgAAAAAAAAAEAD/QQAAAABzdW0vVVQFAAMbtMtcdXgLAAEE6AMAAAToAwAAUEsBAh4DFAAAAAgAe3WTTkQjafoxAAAAMgAAAAoAGAAAAAAAAQAAAP+BPgAAAHN1bS9zdW0uZ29VVAUAAzp8uVx1eAsAAQToAwAABOgDAABQSwECHgMUAAAACAC2SpZOSyDHc2cCAAA+BAAABwAYAAAAAAABAAAA/4GzAAAAbWFpbi5nb1VUBQADOCW9XHV4CwABBOgDAAAE6AMAAFBLBQYAAAAAAwADAOcAAABbAwAAAAA="
var dataFile = 'data:application/zip;base64,' + dataBase64
var dlnk = document.getElementById('dwnldLnk');
dlnk.href = dataFile;
dlnk.click();
Related
I'm trying to read files from my database (varbinary) and add them to a zip file so that users can download all files related to a specific user.
From what I can gather, I need to read the files from the database, create the zip file, read the files into memory and then write that to the file (doing it without this returned a blank zip file).
It will save the files to the zip, but unfortunately the files are all corrupted.
public FileResult DownloadAllDocuments(int userId)
{
// File name
string ZipFilename = DateTime.Now + "_Files.zip";
// Get files from database
List<DocumentVO> Documents = DocumentDAO.DownloadAllDocuments(userId);
var zipFileMemoryStream = new MemoryStream();
using (ZipArchive archive = new ZipArchive(zipFileMemoryStream, ZipArchiveMode.Update, leaveOpen: true))
{
foreach (DocumentVO document in Documents)
{
var entry = archive.CreateEntry(document.fileName, CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
entryStream.Write(document.File, 0, document.File.Length);
}
}
}
zipFileMemoryStream.Seek(0, SeekOrigin.Begin);
return File(zipFileMemoryStream, "application/octet-stream", ZipFilename);
}
Please try these codes instead of return File line
using (MemoryStream ms = new MemoryStream())
{
zip.Save(ms);
Response.ClearHeaders();
Response.ClearContent();
Response.Charset = "";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + ZipFilename);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/zip";
Response.BinaryWrite(ms.ToArray());
}
I've set up a server endpoint that will zip a folder of files and return the zip file. On the client-side, I have code that calls the endpoint and saves the downloaded zip file to disk. All the code runs, but the resultant file is bigger than the zip file on the server and if I try to open the resultant zip file, I get "Windows can't open the file, file is invalid". What am I doing wrong?
Server code:
[Route("projects/files/download")]
[HttpPost]
public ActionResult Post([FromForm] DownloadFileRequest request)
{
string filesPath = ...;
string zipName = ...;
if (!Directory.Exists(filesPath)) {`
return BadRequest("File path not found on server");
}
if (System.IO.File.Exists(zipName)) System.IO.File.Delete(zipName);
System.IO.Compression.ZipFile.CreateFromDirectory(filesPath, zipName);
byte[] fileBytes = System.IO.File.ReadAllBytes(zipName);
FileContentResult zipFile = File(fileBytes, "application/zip", fileName);
return Ok(zipFile);
}
Client code:
Uri uri = new Uri("https://.../projects/files/download");
response = client.PostAsync(uri.ToString(), formContent).Result;
if (response.IsSuccessStatusCode)`
{
using (HttpContent content = response.Content)
{
Stream stream = content.ReadAsStreamAsync().Result;
string path = ...;
stream.Seek(0, SeekOrigin.Begin);
using (Stream streamToWriteTo = File.Open(path, FileMode.Create))
{
stream.CopyTo(streamToWriteTo);
}
}
}
Instead of returning the Ok(zipFile), just return the file:
return File(fileBytes, "application/zip", fileName);
I need to create a file txt and a file with extension dat. After that I want to compress these files into a zip file and to download it.
My problem is that I don't want to save the files before download. So, can I create and download the zip without creating files on server?
I used MemoryStream. Below you can find the code:
public ZipOutputStream CreateZip(MemoryStream memoryStreamControlFile, MemoryStream memoryStreamDataFile)
{
using (var outputMemStream = new MemoryStream())
{
using (var zipStream = new ZipOutputStream(baseOutputStream))
{
zipStream.SetLevel(3); // 0-9, 9 being the highest level of compression
byte[] bytes = null;
// .dat
var nameFileData = CreateFileName("dat");
var newEntry = new ZipEntry(nameFileData) { DateTime = DateTime.Now };
zipStream.PutNextEntry(newEntry);
bytes = memoryStreamDataFile.ToArray();
var inStream = new MemoryStream(bytes);
StreamUtils.Copy(inStream, zipStream, new byte[4096]);
inStream.Close();
zipStream.CloseEntry();
// .suc
var nameFileControl = CreateFileName("suc");
newEntry = new ZipEntry(nameFileControl) { DateTime = DateTime.Now };
zipStream.PutNextEntry(newEntry);
bytes = memoryStreamControlFile.ToArray();
inStream = new MemoryStream(bytes);
StreamUtils.Copy(inStream, zipStream, new byte[4096]);
inStream.Close();
zipStream.CloseEntry();
// .zip
zipStream.IsStreamOwner = false;
zipStream.Close();
outputMemStream.Position = 0;
return zipStream;
}
}
}
I assume you are working with ASP.Net ?
You can put the file contents (stream, etc...) in a byte array, then output that directly to the user in the response, like :
string fileType = "...zip...";
byte[] fileContent = <your file content> as byte[];
int fileSize = 1000;
string fileName = "filename.zip";
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
Response.ContentType = fileType;
Response.OutputStream.Write(fileContent, 0, fileSize);
I followed another post to be able to zip the content of an URL..
When I click my button Download, I "zip" the content of the URL and I save it in the default download folder...
So far this is my code:
WebClient wc = new WebClient();
ZipFile zipFile = new ZipFile();
string filename = "myfile.zip";
zipFile.Password = item.Password;
Stream s = wc.OpenRead(myUrl);
zipFile.AddeEntry(filename, s);
return File(s, "application/zip", filename);
it´s similar to this one (which zips the content of a folder... ) (It works correctly)
ZipFile zipFile = new ZipFile();
zipFile.Password = item.Password;
zipFile.AddDirectory(sourcePath, "");
MemoryStream stream = new MemoryStream();
zipFile.Save(stream);
zipFile.Dispose();
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/zip", fileName);
So, I want to do exactly the same with an URL..
THanks!
at the end I use this code and It works like I wanted...
Thanks to all again!
string fileName = "filename" + ".zip";
MemoryStream stream = new MemoryStream();
ZipFile zipFile = new ZipFile();
WebRequest webRequest = WebRequest.Create(myUrl);
webRequest.Timeout = 1000;
WebResponse webResponse = webRequest.GetResponse();
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
string content = reader.ReadToEnd();
zipFile.AddEntry("myfile.txt", content);
}
zipFile.Save(stream);
zipFile.Dispose();
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/zip", fileName);
The example you provide will create an entry inside your zip file with the contents from the stream but you are doing nothing to save and return the actual zip file. You need to use the creation code from your second example.
// name of zip file
string filename = "myfile.zip";
// filename of content
string contentName = "mypage.html";
WebClient wc = new WebClient();
ZipFile zipFile = new ZipFile();
zipFile.Password = item.Password;
Stream s = wc.OpenRead(myUrl);
zipFile.AddeEntry(contentName, s);
MemoryStream stream = new MemoryStream();
zipFile.Save(stream);
zipFile.Dispose(); // could use using instead
s.Dispose(); // could use using instead....
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/zip", fileName);
this will return a zip file with one file in it called content.html containing the contents of the url stream
I need help in converting a file received from a jquery ajax to byte array. I'm using a plugin called ajaxfileupload then from a jquery ajax call I send a file from a fileupload control to a handler. Here is my
handler code:
if (context.Request.Files.Count > 0)
{
string path = context.Server.MapPath("~/Temp");
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
var file = context.Request.Files[0];
string fileName;
if (HttpContext.Current.Request.Browser.Browser.ToUpper() == "IE")
{
string[] files = file.FileName.Split(new char[] { '\\' });
fileName = files[files.Length - 1];
}
else
{
fileName = file.FileName;
}
string fileType = file.ContentType;
string strFileName = fileName;
FileStream fs = new FileStream("~/Temp/" + strFileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] imagebytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
DBAccess dbacc = new DBAccess();
dbacc.saveImage(imagebytes);
string msg = "{";
msg += string.Format("error:'{0}',\n", string.Empty);
msg += string.Format("msg:'{0}'\n", strFileName);
msg += "}";
context.Response.Write(msg);
}
I'm saving the file to a folder within a project then trying to retrieve that file and save it to the database. I can assure you that the image is being saved to the temp folder. The problem is with the line with (*) the file path is wrong. This is the file path that is being retrieved. "'C:\Program Files\Common Files\Microsoft Shared\DevServer\10.0\~\Temp\2012-06-03 01.25.47.jpg'.". The temp folder is located locally inside my project and I want to retrieved the image within that folder. How can I set the file path to my desired location? Or is there another way to convert a file to byte array after retrieving it from a jquery ajax call?
Credits to these articles:
Save and Retrieve Files from SQL Server Database using ASP.NET
Async file upload with jQuery and ASP.NET
Just these 3 lines will do:
int filelength = file.ContentLength;
byte[] imagebytes = new byte[filelength ];
file.InputStream.Read(imagebytes , 0, filelength );
using (var stream = upload.InputStream)
{
// use stream here: using StreamReader, StreamWriter, etc.
}