I'm trying to download and save an .mp3 file from the internet, but got stuck with stream from the external link:
private void saveSound()
{
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
using (var fs = new IsolatedStorageFileStream("123.mp3", FileMode.Create, iso))
{
//Here should be this Stream from the Internet...
//Uri: "http://my-site.com/mega-popular-song.mp3"
StreamResourceInfo rs = new StreamResourceInfo(stream, "audio/mpeg");
int count = 0;
byte[] buffer = new byte[4096];
while (0 < (count = rs.Stream.Read(buffer, 0, buffer.Length)))
{
fs.Write(buffer, 0, count);
}
fs.Close();
}
}
What should this stream look like? What is the best way to download and save .mp3 files?
I'm sure this article gets you there. Like Bob mentioned, you'll have to use a WebClient. Basically this is the code that does the magic:
wc.OpenReadCompleted += ((s, args) =>
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(fileName))
store.DeleteFile(fileName);
using (var fs = new IsolatedStorageFileStream(fileName, FileMode.Create, store))
{
byte[] bytesInStream = new byte[args.Result.Length];
args.Result.Read(bytesInStream, 0, (int)bytesInStream.Length);
fs.Write(bytesInStream, 0, bytesInStream.Length);
fs.Flush();
}
}
});
But I would read the complete article to fully understand what happens. Hope this helps!
Related
I am writing a code to compress a ZIP file in C# using the built in .NET library:
using System.IO.Compression;
using System.IO;
But, however, when the compression finishes, the code outputs an invalid zip file. It seems like somewhere down the line in the code, the file either did not write properly or close fully. I have used dispose and close to release the resources.
public bool CompressFile(FileInfo theFile)
{
StringBuilder compressSuccess = new StringBuilder();
FileStream sourceFile = File.OpenRead(theFile.FullName.ToString());
FileStream destinationFile = File.Create(theFile.FullName + ".zip");
byte[] buffer = new byte[sourceFile.Length];
sourceFile.Read(buffer, 0, buffer.Length);
using (GZipStream output = new GZipStream(destinationFile,
CompressionMode.Compress, true))
{
output.Write(buffer, 0, buffer.Length);
}
sourceFile.Dispose();
destinationFile.Dispose();
sourceFile.Close();
destinationFile.Close();
return true;
}
What would I been doing wrong? Is it because I am forcing an extension ".zip"?
Following the link suggested by FrankJames, this is an example of code to create a zip file:
var zipFile = #"e:\temp\outputFile.zip";
var theFile = #"e:\temp\sourceFile.txt";
using (var zipToCreate = new FileStream(zipFile, FileMode.Create))
{
using (var archive = new ZipArchive(zipToCreate, ZipArchiveMode.Create))
{
var fileEntry = archive.CreateEntry("FileNameInsideTheZip.txt");
using (var sourceStream = File.OpenRead(theFile))
using (var destStream = fileEntry.Open())
{
var buffer = new byte[sourceStream.Length];
sourceStream.Read(buffer, 0, buffer.Length);
destStream.Write(buffer, 0, buffer.Length);
destStream.Flush();
}
}
}
I see you never used the Flush method that force to write to the stream.
I rewrite your code using a better style (using instead of the dispose).
Try it and let us know:
public bool CompressFile(FileInfo theFile)
{
using (var sourceStream = File.OpenRead(theFile.FullName))
using (var destStream = File.Create(theFile.FullName + ".zip"))
{
var buffer = new byte[sourceStream.Length];
sourceStream.Read(buffer, 0, buffer.Length);
using (var zipStream = new GZipStream(destStream, CompressionMode.Compress, true))
{
zipStream.Write(buffer, 0, buffer.Length);
zipStream.Flush();
}
destStream.Flush();
}
return true;
}
request = MakeConnection(uri, WebRequestMethods.Ftp.DownloadFile, username, password);
response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
//This part of the code is used to write the read content from the server
using (StreamReader responseReader = new StreamReader(responseStream))
{
using (var destinationStream = new FileStream(toFilenameToWrite, FileMode.Create))
{
byte[] fileContents = Encoding.UTF8.GetBytes(responseReader.ReadToEnd());
destinationStream.Write(fileContents, 0, fileContents.Length);
}
}
//This part of the code is used to write the read content from the server
using (var destinationStream = new FileStream(toFilenameToWrite, FileMode.Create))
{
long length = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
destinationStream.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
}
The former ones writes the content to the file but when I try to open the file it says it is corrupted. But the later one does the job perfectly when downloading zip files. Is there any specific reason why the former code doesn't work for zip files as it works perfectly for text files?
byte[] fileContents = Encoding.UTF8.GetBytes(responseReader.ReadToEnd());
You try to interpret a binary PDF file as an UTF-8 text. That just cannot work.
For a correct code, see Upload and download a binary file to/from FTP server in C#/.NET.
Use BinaryWriter and pass it FileStream.
//This part of the code is used to write the read content from the server
using (var destinationStream = new BinaryWriter(new FileStream(toFilenameToWrite, FileMode.Create)))
{
long length = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
destinationStream.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
}
here is my solution that worked for me
C#
public IActionResult GetZip([FromBody] List<DocumentAndSourceDto> documents)
{
List<Document> listOfDocuments = new List<Document>();
foreach (DocumentAndSourceDto doc in documents)
listOfDocuments.Add(_documentService.GetDocumentWithServerPath(doc.Id));
using (var ms = new MemoryStream())
{
using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var attachment in listOfDocuments)
{
var entry = zipArchive.CreateEntry(attachment.FileName);
using (var fileStream = new FileStream(attachment.FilePath, FileMode.Open))
using (var entryStream = entry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
ms.Position = 0;
return File(ms.ToArray(), "application/zip");
}
throw new ErrorException("Can't zip files");
}
don't miss the ms.Position = 0; here
I've got a rare case where a file cannot be read from a UNC path immediately after it was written. Here's the workflow:
plupload sends a large file in chunks to a WebAPI method
Method writes the chunks to a UNC path (a storage server). This loops until the file is completely uploaded.
After a few other operations, the same method tries to read the file again and sometimes it cannot find the file
It only seems to happen after our servers have been idle for a while. If I repeat the upload a few times, it starts to work.
I thought it might be a network configuration issue, or something to do with the file not completely closing before being read again.
Here's part of the code that writes the file (is the filestream OK in this case?)
SaveStream(stream, new FileStream(fileName, FileMode.Append, FileAccess.Write));
Here's SaveStream definition:
private static void SaveStream(Stream stream, FileStream fileStream)
{
using (var fs = fileStream)
{
var buffer = new byte[1024];
var l = stream.Read(buffer, 0, 1024);
while (l > 0)
{
fs.Write(buffer, 0, l);
l = stream.Read(buffer, 0, 1024);
}
fs.Flush();
fs.Close();
}
}
Here's the code that reads the file:
var fileInfo = new FileInfo(fileName);
var exists = fileInfo.Exists;
It's the fileInfo.Exists that is returning false.
Thank you
These kind of errors are mostly due to files not closed yet.
Try passing the fileName to SaveStream and then use it as follows:
private static void SaveStream(Stream stream, string fileName)
{
using (var fs = new FileStream(fileName, FileMode.Append, FileAccess.Write))
{
var buffer = new byte[1024];
var l = stream.Read(buffer, 0, 1024);
while (l > 0)
{
fs.Write(buffer, 0, l);
l = stream.Read(buffer, 0, 1024);
}
fs.Flush();
} // end of using will close and dispose fs properly
}
I am downloading a xml file from the internet and save it in isolated storage. If I try to read it I get an error:
Data at the root level is invalid. Line 1, position 1.
string tempUrl = "http://xxxxx.myfile.xml"; // changed
WebClient client = new WebClient();
client.OpenReadAsync(new Uri(tempUrl));
client.OpenReadCompleted += new OpenReadCompletedEventHandler(delegate(object sender, OpenReadCompletedEventArgs e) {
StreamWriter writer = new StreamWriter(new IsolatedStorageFileStream("myfile.xml", FileMode.Create, FileAccess.Write, myIsolatedStorage));
writer.WriteLine(e.Result);
writer.Close();
});
This is how I download and save the file...
And I try to read it like that:
IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile("myfile.xml", FileMode.Open, FileAccess.Read);
XDocument xmlDoc = XDocument.Load(fileStream);
This is where I get the error...
I have no problem reading the same file without downloading and saving it to isolated storage... so there must be the fault.
This:
writer.WriteLine(e.Result);
doesn't do what you think it does. It's just calling ToString() on a Stream, and writing the result to a file.
I suggest you avoid using a StreamWriter completely, and simply copy from e.Result straight to the IsolatedStorageFileStream:
using (var output = new IsolatedStorageFileStream("myfile.xml", FileMode.Create,
FileAccess.Write, myIsolatedStorage))
{
CopyStream(e.Result, output);
}
where CopyStream would be a method to just copy the data, e.g.
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int read;
while((read = input.Read (buffer, 0, buffer.Length)) > 0)
{
output.Write (buffer, 0, read);
}
}
I am using ICSharpCode.SharpZipLib.Zip.FastZip to zip files but I'm stuck on a problem:
When I try to zip a file with special characters in its file name, it does not work. It works when there are no special characters in the file name.
I think you cannot use FastZip. You need to iterate the files and add the entries yourself specifying:
entry.IsUnicodeText = true;
To tell SharpZipLib the entry is unicode.
string[] filenames = Directory.GetFiles(sTargetFolderPath);
// Zip up the files - From SharpZipLib Demo Code
using (ZipOutputStream s = new
ZipOutputStream(File.Create("MyZipFile.zip")))
{
s.SetLevel(9); // 0-9, 9 being the highest compression
byte[] buffer = new byte[4096];
foreach (string file in filenames)
{
ZipEntry entry = new ZipEntry(Path.GetFileName(file));
entry.DateTime = DateTime.Now;
entry.IsUnicodeText = true;
s.PutNextEntry(entry);
using (FileStream fs = File.OpenRead(file))
{
int sourceBytes;
do
{
sourceBytes = fs.Read(buffer, 0, buffer.Length);
s.Write(buffer, 0, sourceBytes);
} while (sourceBytes > 0);
}
}
s.Finish();
s.Close();
}
You can continue using FastZip if you would like, but you need to give it a ZipEntryFactory that creates ZipEntrys with IsUnicodeText = true.
var zfe = new ZipEntryFactory { IsUnicodeText = true };
var fz = new FastZip { EntryFactory = zfe };
fz.CreateZip("out.zip", "C:\in", true, null);
You have to download and compile the latest version of SharpZipLib library so you can use
entry.IsUnicodeText = true;
here is your snippet (slightly modified):
FileInfo file = new FileInfo("input.ext");
using(var sw = new FileStream("output.zip", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using(var zipStream = new ZipOutputStream(sw))
{
var entry = new ZipEntry(file.Name);
entry.IsUnicodeText = true;
zipStream.PutNextEntry(entry);
using (var reader = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
{
byte[] actual = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, actual, 0, bytesRead);
zipStream.Write(actual, 0, actual.Length);
}
}
}
}
Possibility 1: you are passing a filename to the regex file filter.
Possibility 2: those characters are not allowed in zip files (or at least SharpZipLib thinks so)
try to take out the special character from the file name, i,e replace it.
your Filename.Replace("&", "&");