I am using Uploadify to upload multiple files in my ASP.NET MVC application. In the controller action, I need to check if one of the uploaded files is a zip file, and if yes, I need to check its contents. For the zip functionality I am using the ICSharpCode.SharpZipLib.
When uploading a zip file from say my desktop, I am getting the following error:
Could not find file 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\xyz.zip' on the following line of code:
FileStream fs = System.IO.File.OpenRead(Path.GetFullPath(fileData.FileName));
ZipFile zf = new ZipFile(fs);
How do I get past this error?
[HttpPost]
public ActionResult Upload(HttpPostedFileBase fileData)
{
if (fileData != null && fileData.ContentLength > 0)
{
if (Path.GetExtension(fileData.FileName) == ".zip")
{
FileStream fs = System.IO.File.OpenRead(Path.GetFullPath(fileData.FileName));
ZipFile zf = new ZipFile(fs);
foreach (ZipEntry zipEntry in zf)
{
}
}
else
{
var fileName = Server.MapPath("~/Content/uploads/" + Path.GetFileName(fileData.FileName));
fileData.SaveAs(fileName);
return Json(true);
}
}
return Json(false);
}
HttpPostedFileBase.FileName is the name of the file uploaded, not the location on the file stored on the server. HttpPostedFileBase does not store the file on the server, only as a stream. Your options are either open the stream in memory (if your 3rd party utilies allow for opening streams) or saving the file to a known location, then open it from that location.
Path.GetFullPath gets a full path from the current directory.
That has nothing to do with your HttpUploadedFileBase, which isn't on disk.
You need to pass a stream instead of a file path.
If you want to check if it is a zip file, you could always look at the content-type coming back.
application/zip
This might work for what you are trying to do. Also, just try and look at what the content-type, you might find something more specific to your needs.
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 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.
I am looking to download my files in public folder from One Drive, but it doesn't download the files.
Here is the scenario:
In public folder I have another folder with multiple files in it and is accessible widely.
for test purpose I have shared all the files in public folder (I don't if it's proper way of sharing it).
The following links are provided for me to download the file:
From shared folder link https://onedrive.live.com/redir?resid=DBBC281099F4FE69!646&authkey=!AGRCGuw8Y2_p9mA&ithint=folder%2c.mp3
From public folder link https://onedrive.live.com/redir?resid=DBBC281099F4FE69%21646
Direct link http://1drv.ms/1z9XlW6 -
I am using BackgroundTransferRequest to download the file using below code:
string filePathToDownload = string.Empty, fileName = "111.mp3";
filePathToDownload = "http://1drv.ms/1z9XlW6";
Uri transferUri = new Uri(Uri.EscapeUriString(filePathToDownload), UriKind.RelativeOrAbsolute);
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
transferRequest.Method = "GET";
transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
Uri downloadUri = new Uri(DataSource.TEMPDOWNLOADLOCATION + fileName, UriKind.RelativeOrAbsolute);
transferRequest.DownloadLocation = downloadUri;
transferRequest.Tag = fileName;
The file is 300Kb, but this only downloads 6 Kb.
How can I directly download the file from the links above (any of them)?
thanks!
If you replace the word redir with download in the url you get the raw file instead of the webpage i.e.
https://onedrive.live.com/download?resid=DBBC281099F4FE69%21646
Basically, you can't. Those links are links to the web content that shows the files you have shared. If your scenario doesn't mind asking the user to log in to OneDrive, then you can use the Live SDK to access these files.
To access your public folder from Live SDK, you need to either use Live SDK to get the folder-id for your public folder, or convert the IDs in the URL you copied into the format the Live SDK uses:
folder.<user-id>.<folder-resid>
Where is the part of before the !. In general you shouldn't construct an ID, since it's possible the IDs will change in the future, and instead you should retrieve the ID from the service. However, with the URL you pasted the ID would be:
folder.DBBC281099F4FE69.DBBC281099F4FE69!646
Which will allow you to call
https://apis.live.net:443/v5.0/folder.DBBC281099F4FE69.DBBC281099F4FE69!646/files?access_token=<valid_token>
and retrieve the IDs for the individual files, which you can then download via Live SDK following these details: http://msdn.microsoft.com/en-US/library/dn659726.aspx#download_a_file
For those who are still looking for a response to that question.
The easiest way to find the file path is to go to One Drive on the web and right-click on the file that we want and select Embed. Ξ€hen on the right we see the info window to integrate our file into a page. Inside the iframe is the source of the file. Then we have to replace the word embed with the word download and that's it.
Try something like this
//we first need the file id
string id = string.Empty;
//we need to get all of the filenames stored in the root of the skydrive account
LiveOperationResult result = await this.client.GetAsync("me/skydrive/files");
//lets make a list of all these filenames
List<object> items = result.Result["data"] as List<object>;
//for every filename, check if it is what we want, in this case "sample.txt"
//if it is what we want, get the id and save it to out already defined id value
foreach (object item in items)
{
IDictionary<string, object> file = item as IDictionary<string, object>;
if (file["name"].ToString() == "sample.txt")
{
id = file["id"].ToString();
}
}
//to download the file we need to use the id + "/content"
LiveDownloadOperationResult result2 = await client.DownloadAsync(string.Format("{0}/content", id));
//once the file had downloaded, lets copy it to IsolatedStorage
Stream stream = result2.Stream;
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fileToSave = storage.OpenFile("sample.txt", FileMode.Create, FileAccess.ReadWrite))
{
stream.CopyTo(fileToSave);
stream.Flush();
stream.Close();
}
}
here client is the object of LiveConnectClient class.
Import
using Microsoft.Live;
using Microsoft.Live.Controls;
Here is use txt file as an example. Go through this example:http://www.baileystein.com/2013/10/20/skydrive-how-to-upload-and-download-a-text-file-on-wp8/
I am trying to convert an entire azure blob storage folder and its contents to a zip file .Inside this folder ,I have different types of files eg, .txt,.mp3,.zip files .But once the folder is converted to zip file I noticed that all the .zip file types got corrupted,.How can I prevent my zip files from corrupted. I am using Ionic.Zip library to generate zip files
Here is the code I am using .Here I am able to generate and download the zip file successfully with all other filetypes except the inner zip files.
var allFiles = directory.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true }).Where(x => x.GetType() == typeof(CloudBlockBlob)).Cast<CloudBlob>();
string xyzblob = directory.Uri.ToString().TrimEnd('/');
var dBlob = blobClient.GetBlobReference(xyzblob);
byte[] fileBytes = null;
fileBytes = dBlob.DownloadByteArray();
foreach (var file in allFiles)
{
using (var fileStream = new MemoryStream(fileBytes))
{
var entryName = file.Uri.ToString().Replace(directory.Uri.ToString(), "");
zipOutputStream.PutNextEntry(entryName);
fileStream.Seek(0, SeekOrigin.Begin);
int count = fileStream.Read(fileBytes, 0, fileBytes.Length);
while (count > 0)
{
zipOutputStream.Write(fileBytes, 0, count);
count = fileStream.Read(fileBytes, 0, fileBytes.Length);
if (!Response.IsClientConnected)
{
break;
}
Response.Flush();
}
fileStream.Close();
}
}
zipOutputStream.Close();
More details
I am downloading a folder ,."myFolder" and its contents from azure blob as a zip file eg, myfolders.zip.
Here is how the file structure inside "myFolder" /azure blob
MyFolder/mymusic/ test.mp3
MyFolder/mytext/ newtext.txt
MyFolder/MyZipfiles/ myzip.zip
My code I posted above will generate a zip all the contents of the folder to create "MyFolder.zip" and will download automatically .Now if you unzip "MyFolder.zip" file , due to some reason , the myzip.zip is getting corrupted.If I try to open myzip.zip file ,its showing a message "windows cannot open the folder ,the compressed zipped folder "myzip.zip" is invalid"
Please help me find a solution so that the .zip files wont get corrupted
I tried to download to stream ,but same results.,The inner zip files are getting corrupted.all other file types are in good shape.
zipOutputStream.PutNextEntry(entryName);
destBlob.DownloadToStream(zipOutputStream);
I am assuming you already tried downloading one of those zip files and opening it, right?
If that is the case, one thing I would suggest is to eliminate the intermediate fileBytes array completely. Using fileBytes as the buffer to fileStream and then reading from fileStream to fileBytes might be the culprit. On the other hand, you start from offset 0 and write to the beginning of fileBytes anyway, so it might be working just fine.
In any case, a more efficient solution is; you can call PutNextEntry and then call the blob object's DownloadToStream method by passing in the zip stream itself. That would simply copy the entire blob directly into the zip stream without having to manage an intermediate buffer.
When it starts to pick the .zip file ,I added BlobReference to .zip file and this resolved the issue
dBlob = blobClient.GetBlobReference(entryName.EndsWith(".zip") ? file.Uri.ToString() : xyzblob);
zipOutputStream.PutNextEntry(entryName);
dBlob.DownloadToStream(zipOutputStream);
Is there a simple way to get the FileInfo object from an HttpPostedFileBase? I realize I can save the file then do something like DirectoryInfo.GetFiles and then loop through the files looking for my file, but is there any simpler way to do this for a given file?
There's no FileInfo associated to an uploaded file. Only the filename is sent as parameter as well as the file stream itself. So that's what you could query:
HttpPostedFileBase file = ...
string filename = file.FileName;
int fileSize = file.ContentLength;
string contentType = file.ContentType;
using (Stream stream = file.InputStream)
{
// do something with the file contents here
}
To better understand what gets sent from the client I invite you to read the multipart/form-data specification.
The FileInfo object contains things like LastModified and LastAccessed date which is not an information that is sent when a file is uploaded. If you save the file on your web server disk and then retrieve the FileInfo from it bear in mind that what you will be retrieving is the information about this file on the server and not on the client simply because this information is never sent when a file is uploaded.