Uploading files and preventing duplicates by knowing to update the file - asp.net

In our system, when a user uploads a file it is stored in a unique file system structure and a database record is generated. A file is uploaded via the webbrowser via XMLHttpRequest. The file then gets moved from the temporary upload area into the FS.
How can I detect that a file after being uploaded already exists in my FS?
If the file uploaded is the same as one already uploaded.
If the file is the same file, but the uploaded content has been updated which
means I need to update the file in the FS.
I am ignoring file names as a way of knowing if the file already exists. A filename cannot be considered unique. An example is that some cameras name photos using an incremental number that rolls over after a time.
When a file is uploaded via the web browser, the source file structure is masked. E.g. C:\Users\Drive\File\Uploaded\From. So I cant use the that to figure out if the file has already been uploaded.
How do I know the file being uploaded already exists because its content is the same. Or it exists but because the uploaded file has been changed, so I can just update the file?
Microsoft Word documents create a challenge as Word regenerates the file on every save.
In a situation where the user renames a file on their own accord, I could say tough luck.

I would start with finding files that are the same via an SHA Hash. You could use something like this to get a list of files that have the same hash as your newly uploaded file then take some action.
Just an example of getting the hash of the new file:
string newfile;
using(FileStream fs = new FileStream( string newfile;
using(FileStream fs = new FileStream("C:\\Users\\Drive\\File\\Uploaded\\From\\newfile.txt", FileMode.Open))
{
using (System.Security.Cryptography.SHA1Managed sha1 = new System.Security.Cryptography.SHA1Managed())
{
newfile = BitConverter.ToString(sha1.ComputeHash(fs));
}
}
This goes through all files and gets a list of file names and hashes
var allfiles = Directory.GetFiles(#"var allfiles = Directory.GetFiles(#"C:\Users\Drive\File\Uploaded\From\", "*.*")
.Select(
f => new
{
FileName = f,
FileHash = new System.Security.Cryptography.SHA1Managed()
.ComputeHash(new FileStream(f,
FileMode.Open,
FileAccess.Read))
})
.ToList();
foreach(var fi in allfiles){
if(newfile == BitConverter.ToString(fi.FileHash))
Console.WriteLine("Match!!!");
Console.WriteLine(fi.FileName + ' ' + BitConverter.ToString(fi.FileHash));
}
}", ".")
.Select(
f => new
{
FileName = f,
FileHash = new System.Security.Cryptography.SHA1Managed()
.ComputeHash(new FileStream(f,
FileMode.Open,
FileAccess.Read))
})
.ToList();
This loops through them all and looks for a match to the new one.
foreach(var fi in allfiles){
if(newfile == BitConverter.ToString(fi.FileHash))
Console.WriteLine("Match!!!");
Console.WriteLine(fi.FileName + ' ' + BitConverter.ToString(fi.FileHash));
}
Ideally you would save this hash when the file is uploaded since this is very intense to recompute.

Related

Convert Byte Array to pdf for UWP

I am working on Xamarin.Forms-UWP.
I want to convert byte array stored in the database to pdf for Windows phone.
I know how to convert
var base64Binarystr = "ABCDS"
byte[] bytes = Convert.FromBase64String(base64Binarystr );
Can anyone help as how to display pdf? Just a pointer- I have multiple pdf files so I cannot add all the files to the application or store on the disk.
Appreciate for any pointers on this.
Thanks!
Every received file can be stored with the same name (I used "my.pdf") then there is no risk for too many files stored. If you need to cache files then you can give different names. The pdf viewer didn't want to show files from Local, Temp or Downloads folder for me though I tried ms-appdata, so I had to move the file from Local folder to Assets to display the way viewer "wants" it via ms-appx-web. Downloads folder also has a problem with CreationCollisionOption.ReplaceExisting, it says invalid parameter if file already exists instead of replacing it but Local and Temporary folder behave correctly.
/////////////// store pdf file from internet, move it to Assets folder and display ////////////////////
//bytes received from Internet. Simulated that by reading existing file from Assets folder
var pdfBytes = File.ReadAllBytes(#"Assets\Content\samplepdf.pdf");
try
{
StorageFolder storageFolder = ApplicationData.Current.LocalFolder; //or ApplicationData.Current.TemporaryFolder
StorageFile pdfFile = await storageFolder.CreateFileAsync("my.pdf", CreationCollisionOption.ReplaceExisting);
//write data to created file
await FileIO.WriteBytesAsync(pdfFile, pdfBytes);
//get asets folder
StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder assetsFolder = await appInstalledFolder.GetFolderAsync("Assets");
//move file from local folder to assets
await pdfFile.MoveAsync(assetsFolder, "my.pdf", NameCollisionOption.ReplaceExisting);
}
catch (Exception ex)
{
}
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", "ms-appx-web:///Assets/my.pdf")); //local pdf

provider.FileData null in ReadAsMultipartAsync with media files

I am uploading files by using HTML File Upload control and passing data to ASP.NET Web API. Everything is working fine when I upload image or any text file or xml file. but it's giving error while I upload media files (mp3, mp4).
My code is,
string path = "//My path";
MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(path);
var task = Request.Content.ReadAsMultipartAsync(provider);
return await task.ContinueWith<bool>(t =>
{
string originalSavedAt = "";
foreach (MultipartFileData file in provider.FileData)
{
originalSavedAt = file.LocalFileName;
}
return true;
}, TaskScheduler.FromCurrentSynchronizationContext());
In above code, When I upload image file, it show me values in provider. FileData (provider.FileData.count is 1) in foreach loop.
But it is null (provider.FileData.count is 0) when I upload media file.
Status is failure in task lembda expression during media file upload, but status is RanToCompletion during image upload.
Do I need to add anything for media files. ?

Asp.net Multiple files download

Im trying to search and download the files uploaded to the database,I can able to retrieve the files from the database.
Downloading single file works but cant download multiple files at a time,I have read about downloading as a zip file,Can anyone help??????
using (sampledbase dbcontext = new sampledbase ())
{
ZipFile zip = new ZipFile();
long id = Convert.ToInt64(Request.QueryString["id"]);
System.Nullable<long> fileid = id;
var query = dbcontext.searchfile(ref fileid );
foreach (var i in query)
{
byte[] binarydata = i.Data.ToArray();
Response.AddHeader("content-disposition", string.Format("attachment; filename =\"{0}\"", i.Name));
Response.BinaryWrite(binarydata);
Response.ContentType = i.ContentType;
Response.End();
}
}
I see that you are using ZipFile so you are in the right direction. In order to zip your files, you can save your files in a directory and zip the directory using this code :
string startPath = #"c:\example\start";
string zipPath = #"c:\example\result.zip";
ZipFile.CreateFromDirectory(startPath, zipPath);
In your case, look at the data type returned by dbcontext.searchfile() and save the content to a directory using something like StreamWriter. Looking at your code, the type seems to be a byte[], you can see this link to learn how to save the bytes in a file : Write bytes to file
Another solution is to zip directly the bytes[] : Create zip file from byte[]

How to update a PDF without creating a new PDF?

I am required to replace a word in an existing PDF AcroField with another word. I am using PDFStamper of iTEXTSHARP to do the same and it is working fine. But, in doing so it is required to create a new PDF and i would like the change to be reflected in the existing PDF itself. If I am setting the destination filename same as the original filename then no change is being reflected.I am new to iTextSharp , is there anything I am doing wrong? Please help.. I am providing the piece of code I am using
private void ListFieldNames(string s)
{
try
{
string pdfTemplate = #"z:\TEMP\PDF\PassportApplicationForm_Main_English_V1.0.pdf";
string newFile = #"z:\TEMP\PDF\PassportApplicationForm_Main_English_V1.0.pdf";
PdfReader pdfReader = new PdfReader(pdfTemplate);
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
PdfReader reader = new PdfReader((string)pdfTemplate);
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(newFile, FileMode.Create, FileAccess.ReadWrite)))
{
AcroFields form = stamper.AcroFields;
var fieldKeys = form.Fields.Keys;
foreach (string fieldKey in fieldKeys)
{
//Replace Address Form field with my custom data
if (fieldKey.Contains("Address"))
{
form.SetField(fieldKey, s);
}
}
stamper.FormFlattening = true;
stamper.Close();
}
}
}
As documented in my book iText in Action, you can't read a file and write to it simultaneously. Think of how Word works: you can't open a Word document and write directly to it. Word always creates a temporary file, writes the changes to it, then replaces the original file with it and then throws away the temporary file.
You can do that too:
read the original file with PdfReader,
create a temporary file for PdfStamper, and when you're done,
replace the original file with the temporary file.
Or:
read the original file into a byte[],
create PdfReader with this byte[], and
use the path to the original file for PdfStamper.
This second option is more dangerous, as you'll lose the original file if you do something that causes an exception in PdfStamper.

The given path's format is not supported

I am getting the following error while uploading the file from my local drive.
The given path's format is not supported.
The code is given.
Please tell me what changes I have to make.
string file0 = MapPathReverse(FileUpload1.PostedFile.FileName);// Get virtual path
string conversationFileSource = Server.MapPath(file0);
StreamReader file = new StreamReader(conversationFileSource);
If you want to access the input stream of the uploaded file:
using (StreamReader reader = new StreamReader(FileUpload1.PostedFile.InputStream))
{
...
}
If you want to save the uploaded file on some folder on your server:
var uploadsFolder = Server.MapPath("~/uploads");
var file = Path.Combine(uploadsFolder, Path.GetFileName(FileUpload1.PostedFile.FileName));
FileUpload1.PostedFile.SaveAs(file);

Resources