Answered by:
How to generate hash value of file in asp.net to determine if file exists in Google Drive

Question
-
User-846837922 posted
I have a program whereby I will be able to upload, download, delete files to my Google Drive. Now, the issue that I am encountering is that I am able to generate the hash value of each files but I do not know how to check the hash value of the file that i want to upload with the hash value of the existing files in the Google Drive. If there is an existing hash already, then a message pop-up should appear and inform the user that the file is a duplicate and the user would have to reupload another file. I am unsure on where or how to insert the code for generating the respective hash alongside the message pop-up.
This is the code for my GetGoogleDrive.cshtml file.
@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { <p> <label for="file">Upload file:</label> <input type="file" name="file" id="file" /> <input type="submit" value="Upload" id="fileUpload" /> <script> $('#fileUpload').click(function (e) { if ($('#file').val() === "") { Swal.fire({ title: 'Nothing', text: 'No file selected', type: 'error', confirmButtonText: 'Again!!', timer: 4000 }) } else { Swal.fire({ title: 'Wait awhile...', text: 'File will be uploaded shortly', type: 'success', confirmButtonText: 'Okay, cool', timer: 4000 }) } }); </script>
This is the code for my upload controller class.
[HttpPost] public ActionResult UploadFile(HttpPostedFileBase file) { GoogleDriveFilesRepository.FileUpload(file); return RedirectToAction("GetGoogleDriveFiles"); }
And this is the code for my Google Drives modal class.
public static void FileUpload(HttpPostedFileBase file) { if (file != null && file.ContentLength > 0) { DriveService service = GetService(); string path = Path.Combine(HttpContext.Current.Server.MapPath("~/GoogleDriveFiles"), Path.GetFileName(file.FileName)); file.SaveAs(path); HashGenerator(path); compareHash(HashGenerator(path)); var FileMetaData = new Google.Apis.Drive.v3.Data.File(); FileMetaData.Name = Path.GetFileName(file.FileName); FileMetaData.MimeType = MimeMapping.GetMimeMapping(path); FilesResource.CreateMediaUpload request; using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Open)) { request = service.Files.Create(FileMetaData, stream, FileMetaData.MimeType); request.Fields = "id"; request.Upload(); } } }
EDIT:
These are the codes for my generate hash and compare hash. When my code runs, the exception is thrown when the file is the same hash, but when it is a new file, then the code will crash with this error.
System.IO.FileNotFoundException: Could not find file 'C:\Users\jpvon\source\repos\GoogleDriveRestApi_v3\GoogleDriveRestApi_v3\GoogleDriveFiles\IC.pdf'.
public static string HashGenerator(string path) { using (var md5 = MD5.Create()) { using (var stream = new FileStream(path, FileMode.Open)) { return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", null).ToLower(); } } } public static void compareHash(string path) { DriveService service = GetService(); FilesResource.ListRequest FileListRequest = service.Files.List(); IList<Google.Apis.Drive.v3.Data.File> files = FileListRequest.Execute().Files; List<GoogleDriveFiles> FileList = new List<GoogleDriveFiles>(); foreach (var file in files) { if (file.Md5Checksum.Equals(path)) { throw new Exception("File already exists"); } } }
Am I able to generate the hash from razor via JS or i have to do from c# side?
Saturday, October 19, 2019 6:14 PM
Answers
-
User665608656 posted
Hi JasonPhang,
For the upload file, this error message appears when I upload the file.
Exception Details: System.IO.FileNotFoundException: Could not find file 'C:\Users\jpvon\source\repos\GoogleDriveRestApi_v3\GoogleDriveRestApi_v3\GoogleDriveFiles\Appendix 1 - Dress Code.pdf'.
And the error points to this line from the hash generator code.
using (var stream = new FileStream(path, FileMode.Open))
This error indicates that you need to check that the path to your file is correct.
You can refer to this link : https://stackoverflow.com/a/5695316
And if I understand rightly what you wrote, say for example it returns true for the file not equal, then it should pass this value of true to the ajax jquery method, yes? if it is false, then it will pass false?That's what I mentioned earlier. I tried to modify your method logic and use it with ajax. You can refer to it:
<script> $(function () { $('#fileUpload').click(function (e) { event.preventDefault(); var formData = new FormData($('form')[0]); $.ajax({ url: "/C_1022_2160860/UploadFile", type: 'Post', success: function (result) { if (result) { alert("upload success!"); location.href = "/C_1022_2160860/GetGoogleDriveFiles"; } else { alert("File already exists"); } }, data: formData, cache: false, contentType: false, processData: false }); if ($('#file').val() === "") { Swal.fire({ title: 'Nothing', text: 'No file selected', type: 'error', confirmButtonText: 'Again!!', timer: 4000 }) } else { Swal.fire({ title: 'Wait awhile...', text: 'File will be uploaded shortly', type: 'success', confirmButtonText: 'Okay, cool', timer: 4000 }) } }); }) </script>
<form enctype="multipart/form-data">
<label for="file">Upload file:</label> <input type="file" name="file" id="file" /> <input type="button" value="Upload" id="fileUpload" /> </form>public class C_1022_2160860Controller : Controller { // GET: C_1022_2160860 public ActionResult Index() { return View("Index"); } public ActionResult GetGoogleDriveFiles() { return View("GetGoogleDriveFiles"); } [HttpPost] public JsonResult UploadFile(HttpPostedFileBase file) { bool kk = FileUpload(file); return Json(kk, JsonRequestBehavior.AllowGet); } public static bool FileUpload(HttpPostedFileBase file) { if (file != null && file.ContentLength > 0) { DriveService service = GetService(); string path = Path.Combine(HttpContext.Current.Server.MapPath("~/GoogleDriveFiles"), Path.GetFileName(file.FileName)); file.SaveAs(path); HashGenerator(path); if (compareHash(HashGenerator(path))) { var FileMetaData = new Google.Apis.Drive.v3.Data.File(); FileMetaData.Name = Path.GetFileName(file.FileName); FileMetaData.MimeType = MimeMapping.GetMimeMapping(path); FilesResource.CreateMediaUpload request; using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Open)) { request = service.Files.Create(FileMetaData, stream, FileMetaData.MimeType); request.Fields = "id"; request.Upload(); } return true; } return false; } return false; } public static string HashGenerator(string path) { using (var md5 = MD5.Create()) { using (var stream = new FileStream(path, FileMode.Open)) { return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", null).ToLower(); } } } public static bool compareHash(string path) { DriveService service = GetService(); FilesResource.ListRequest FileListRequest = service.Files.List(); IList<Google.Apis.Drive.v3.Data.File> files = FileListRequest.Execute().Files; List<GoogleDriveFiles> FileList = new List<GoogleDriveFiles>(); foreach (var file in files) { if (file.Equals(path)) { return false; } return true; } return true; } }
Here is the result:
Best Regards,
YongQing.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Wednesday, October 23, 2019 2:41 AM
All replies
-
User-474980206 posted
Google use a md5 hash. In .net see:
https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.md5?view=netframework-4.8
If you use the browser html 5 api to access the file, google for a md5 check sum
Saturday, October 19, 2019 6:25 PM -
User665608656 posted
Hi JasonPhang,
According to your description, could you tell us the detailed code of the HashGenerator method in your code?
As far as I know, google drive has his own methods to generate hash values. The hash values generated by your local methods and the values generated on google drive are unmatched.
If you want to determine whether the current file has been uploaded, you can decide whether to let the file upload by judging whether the file name is the same.
Best Regards,
YongQing.
Monday, October 21, 2019 9:36 AM -
User-846837922 posted
I have already edited my code. Kindly check and let me know how should I approach this problem. The file name would not be so secure as I can upload same file names but with different content and it will still be uploaded, yes? I want to eliminate that redundancy but I am not sure whether the hash generator code is right or not. Should I run that hash code from razor or in c#?
Monday, October 21, 2019 9:47 AM -
User665608656 posted
Hi JasonPhang,
According to your desctription, could you tell us which code is wrong when you upload a new file, and the specific error details, which is more like the problem of your document path.
After the compareHash method is used, if the file is repeated, I suggest that you don't need to throw an exception directly. Instead, you need to return false to determine whether you need to perform the operation of uploading the file later.
In the UploadFile method, you can return the bool type parameter and the boolean value received in the ajax jquery method.
If it is true, you will jump to the corresponding action method. Otherwise,direct alert popup file duplicate information.
I suggest you use the ajax method of jquery instead of the form submission method.
$.ajax({ type: 'Post', url: "/Home/UploadFile", data: //the parameter of your upload file, success: function (data) { if (data) { //redirect to another action } else { alert("File already exists"); } } });
Best Regards,
YongQing.
Tuesday, October 22, 2019 9:32 AM -
User-846837922 posted
For the upload file, this error message appears when I upload the file.
Exception Details: System.IO.FileNotFoundException: Could not find file 'C:\Users\jpvon\source\repos\GoogleDriveRestApi_v3\GoogleDriveRestApi_v3\GoogleDriveFiles\Appendix 1 - Dress Code.pdf'.
And the error points to this line from the hash generator code.
using (var stream = new FileStream(path, FileMode.Open))
I am not sure how to read those files that I want to upload to generate its hash upon clicking upload button.
What I want would be if the hash is not the same, then it should upload, otherwise, it will not upload. Would something like this work? Because honestly, I am not too sure which part to return false..
public static Boolean compareHash(string path) { DriveService service = GetService(); FilesResource.ListRequest FileListRequest = service.Files.List(); IList<Google.Apis.Drive.v3.Data.File> files = FileListRequest.Execute().Files; List<GoogleDriveFiles> FileList = new List<GoogleDriveFiles>(); foreach (var file in files) { if (!file.Md5Checksum.Equals(path)) { return true; Upload the file as usual //
} else { return false;inform user that file is duplicated and it will not be uploaded // } } return false; }And if I understand rightly what you wrote, say for example it returns true for the file not equal, then it should pass this value of true to the ajax jquery method, yes? if it is false, then it will pass false?
I am not too sure for the ajax part because I do not quite get the part of jumping to the action method and obtaining the data value.
<script> function checkFile() { } return $.ajax( { type: 'Post', url: "/Home/UploadFile", data://param of file to upload from where I should get success: function(data) { if (data.d) { //if i want to upload, then how to jump to the action method } else { alert("file already exists"); } } }); </script>
I am very sorry and apologize if it seems stupid my questions but just I am fairly new to ajax and asp.net but I want to give it a shot with this. I hope that you can assist me with these last few parts..
Tuesday, October 22, 2019 1:15 PM -
User-846837922 posted
How do I call the compare hash boolean value from the razor upload file? That is my problem I am facing.
Tuesday, October 22, 2019 2:18 PM -
User665608656 posted
Hi JasonPhang,
For the upload file, this error message appears when I upload the file.
Exception Details: System.IO.FileNotFoundException: Could not find file 'C:\Users\jpvon\source\repos\GoogleDriveRestApi_v3\GoogleDriveRestApi_v3\GoogleDriveFiles\Appendix 1 - Dress Code.pdf'.
And the error points to this line from the hash generator code.
using (var stream = new FileStream(path, FileMode.Open))
This error indicates that you need to check that the path to your file is correct.
You can refer to this link : https://stackoverflow.com/a/5695316
And if I understand rightly what you wrote, say for example it returns true for the file not equal, then it should pass this value of true to the ajax jquery method, yes? if it is false, then it will pass false?That's what I mentioned earlier. I tried to modify your method logic and use it with ajax. You can refer to it:
<script> $(function () { $('#fileUpload').click(function (e) { event.preventDefault(); var formData = new FormData($('form')[0]); $.ajax({ url: "/C_1022_2160860/UploadFile", type: 'Post', success: function (result) { if (result) { alert("upload success!"); location.href = "/C_1022_2160860/GetGoogleDriveFiles"; } else { alert("File already exists"); } }, data: formData, cache: false, contentType: false, processData: false }); if ($('#file').val() === "") { Swal.fire({ title: 'Nothing', text: 'No file selected', type: 'error', confirmButtonText: 'Again!!', timer: 4000 }) } else { Swal.fire({ title: 'Wait awhile...', text: 'File will be uploaded shortly', type: 'success', confirmButtonText: 'Okay, cool', timer: 4000 }) } }); }) </script>
<form enctype="multipart/form-data">
<label for="file">Upload file:</label> <input type="file" name="file" id="file" /> <input type="button" value="Upload" id="fileUpload" /> </form>public class C_1022_2160860Controller : Controller { // GET: C_1022_2160860 public ActionResult Index() { return View("Index"); } public ActionResult GetGoogleDriveFiles() { return View("GetGoogleDriveFiles"); } [HttpPost] public JsonResult UploadFile(HttpPostedFileBase file) { bool kk = FileUpload(file); return Json(kk, JsonRequestBehavior.AllowGet); } public static bool FileUpload(HttpPostedFileBase file) { if (file != null && file.ContentLength > 0) { DriveService service = GetService(); string path = Path.Combine(HttpContext.Current.Server.MapPath("~/GoogleDriveFiles"), Path.GetFileName(file.FileName)); file.SaveAs(path); HashGenerator(path); if (compareHash(HashGenerator(path))) { var FileMetaData = new Google.Apis.Drive.v3.Data.File(); FileMetaData.Name = Path.GetFileName(file.FileName); FileMetaData.MimeType = MimeMapping.GetMimeMapping(path); FilesResource.CreateMediaUpload request; using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Open)) { request = service.Files.Create(FileMetaData, stream, FileMetaData.MimeType); request.Fields = "id"; request.Upload(); } return true; } return false; } return false; } public static string HashGenerator(string path) { using (var md5 = MD5.Create()) { using (var stream = new FileStream(path, FileMode.Open)) { return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", null).ToLower(); } } } public static bool compareHash(string path) { DriveService service = GetService(); FilesResource.ListRequest FileListRequest = service.Files.List(); IList<Google.Apis.Drive.v3.Data.File> files = FileListRequest.Execute().Files; List<GoogleDriveFiles> FileList = new List<GoogleDriveFiles>(); foreach (var file in files) { if (file.Equals(path)) { return false; } return true; } return true; } }
Here is the result:
Best Regards,
YongQing.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Wednesday, October 23, 2019 2:41 AM -
User-846837922 posted
The issue now is that it can upload but it does not differentiate between the duplicated files and new file. When i tried to submit the same file again, it had success message displayed. But when I clicked on the upload button without selecting any files, it says "file already exists". So if new or same file upload, message sucess, but if just click on the upload button without any file, file already exists. What could be the issue here? I tried to follow your code and replicate it. Anything I am missing?
This is the code for the .cshtml
<center> <div style="width:80%; text-align:left;"> <form enctype="multipart/form-data"> <label for="file">Upload file:</label> <input type="file" name="file" id="file" /> <input type="submit" value="Upload" id="fileUpload" /> </form> <script> $(function () { $('#fileUpload').click(function (e) { event.preventDefault(); var formData = new FormData($('form')[0]); $.ajax({ url: "/Home/UploadFile", type: 'Post', sucess: function (result) { if (result) { alert("Upload sucess"); location.href = "/Home/GetGoogleDriveFiles"; } else { alert("File already exists"); } }, data: formData, cache: false, contentType: false, processData: false }); }) </script> </div> </center>
This is the controller method.
[HttpPost] public JsonResult UploadFile(HttpPostedFileBase file) { bool kk = GoogleDriveFilesRepository.FileUpload(file); return Json(kk, JsonRequestBehavior.AllowGet); }
This is the hash generator, compare hash and upload file method.
public static bool FileUpload(HttpPostedFileBase file) { if (file != null && file.ContentLength > 0) { DriveService service = GetService(); string path = Path.Combine(HttpContext.Current.Server.MapPath("~/GoogleDriveFiles"),Path.GetFileName(file.FileName)); file.SaveAs(path); HashGenerator(path); if(compareHash(HashGenerator(path))) { var FileMetaData = new Google.Apis.Drive.v3.Data.File(); FileMetaData.Name = Path.GetFileName(file.FileName); FileMetaData.MimeType = MimeMapping.GetMimeMapping(path); FilesResource.CreateMediaUpload request; using (var stream = new FileStream(path, FileMode.Open)) { request = service.Files.Create(FileMetaData, stream, FileMetaData.MimeType); request.Fields = "id"; request.Upload(); } return true; } return false; } return false; } public static string HashGenerator(string path) { using (var md5 = MD5.Create()) { using (var stream = new FileStream(path, FileMode.Open)) { return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "null").ToLower(); } } } public static bool compareHash(string path) { DriveService service = GetService(); FilesResource.ListRequest FileListRequest = service.Files.List(); IList<Google.Apis.Drive.v3.Data.File> files = FileListRequest.Execute().Files; List<GoogleDriveFiles> FileList = new List<GoogleDriveFiles>(); foreach (var file in files) { if (file.Equals(path)) { return false; } return true; } return true; }
Wednesday, October 23, 2019 11:16 AM -
User753101303 posted
Hi,
It does what the code asked for. If no file is uploaded, the FileUpload methods return false (as for an existing file) and the client side shows that too specific message.
Not sure how you want to solve that (for example checking that using JavaScript or returning more than a done/not done code ?).
Edit: the Google API also returns just a bool when you upload a file ?
Wednesday, October 23, 2019 12:09 PM -
User-846837922 posted
<script> $('#fileUpload').click(function (e) { if ($('#file').val() === "") { Swal.fire({ title: 'Nothing', text: 'No file selected', type: 'error', confirmButtonText: 'Again!!', timer: 4000 }); } else { event.preventDefault(); var formData = new FormData($('form')[0]); $.ajax({ url: "/Home/UploadFile", type: 'Post', success: function (result) { if (result) { alert("upload success!"); location.href = "/Home/GetGoogleDriveFiles"; } else { alert("Upload not sucess"); } }, data: formData, cache: false, contentType: false, processData: false }); } } ); </script>
This code block now alerts a message should no file be selected. It will alert the user to submit a file. However, the code is still unable to distinguish between the new or already existing file meaning that irregardless of whether it is a new or existing file, it is uploaded.
PatriceSc
Edit: the Google API also returns just a bool when you upload a file ?I am not too sure about that. Which is why I wanted clearer clarification. From what I understand, if the file is a duplicate, it should return false to the upload file method and the message "file not success" should be triggered like the gif posted
Wednesday, October 23, 2019 3:17 PM -
User665608656 posted
Hi JasonPhang,
According to your description, if you want to give a special prompt in the case of no uploaded file, you can change the returned true or false to return a specific description string.
Now you need to be clear that your js is not actually used to compare whether the files are the same. The code you compare whether the files are the same is written in the controller, that is, the compareHash method. This is the method you provide to compare the hash value.
According to your meaning, the code does not identify whether the uploaded files are duplicate, and did you use code debugging to analyze whether the compareHash method works?
In my first reply, I mentioned that the file uploading on Google drive to generate hash value uses the unique method of Google drive, which is different from the method created locally like this which is you provided.
public static string HashGenerator(string path) { using (var md5 = MD5.Create()) { using (var stream = new FileStream(path, FileMode.Open)) { return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", null).ToLower(); } } }
That is to say, even if you upload the same file, the judgment result is still different.In js, you only prompt with the result which is true judged in the controller, so the js side always reminds that the upload is successful.
I suggest you can check the use of ajax in mvc : Using AJAX In ASP.NET MVC
Best Regards,
YongQing.
Thursday, October 24, 2019 2:09 AM -
User-846837922 posted
According to your description, if you want to give a special prompt in the case of no uploaded file, you can change the returned true or false to return a specific description string.I was able to get this resolved via this code block. So for this case, when no file is being selected a message saying "no file selected" is being displayed to the user.$('#fileUpload').click(function (e) { if ($('#file').val() === "") { Swal.fire({ title: 'Nothing', text: 'No file selected', type: 'error', confirmButtonText: 'Again!!', timer: 4000 }); }
In my first reply, I mentioned that the file uploading on Google drive to generate hash value uses the unique method of Google drive, which is different from the method created locally like this which is you provided.Yes, I remember that which is why if since the hash value of my own code is different than the hash generated by Google Drive, then I do not see the relevancy of the GenerateHash code, yes? If i delete it, I believe that there is no difference as the CompareHash can operate without it.In js, you only prompt with the result which is true judged in the controller, so the js side always reminds that the upload is successful.But i followed your code for the ajax and the controller, should I not get the same response as you?
Thursday, October 24, 2019 2:23 AM -
User-846837922 posted
In js, you only prompt with the result which is true judged in the controller, so the js side always reminds that the upload is successful.Am I able to return a bool value or in a way that it will be able to distinguish whether the file is new or same. because i followed what you did or do i need to adjust the code?
Thursday, October 24, 2019 2:53 AM -
User665608656 posted
Hi JasonPhang,
According to your current error information, you don't need to change the logic between your foreground code and controller code.
In fact, your current error is the problem of verifying the hash value in the controller.
I suggest you reopen a new thread and raise the issue of verifying that the hash value of Google drive files are different from that of your local file generation in your controller.
Best Regards,
YongQing.
Thursday, October 24, 2019 9:54 AM -
User-846837922 posted
Just a quick question, it just based on the gif and code you posted, you were able to succesfully differentiate between the new file and the existing file in the Google Drive, yes?
Thursday, October 24, 2019 1:43 PM -
User665608656 posted
Hi JasonPhang,
No, I just modified the logic of the controller and the cshtml page based on the requirements you mentioned.
Because the code you gave is not complete, I did not compare the hash value. I just set a fixed value and let it return true or false.
Best Regards,
YongQing.
Friday, October 25, 2019 1:30 AM -
User-846837922 posted
I see. Thanks for the advice and help though. I guess I just need to work on the logic of the compare hash part.
Friday, October 25, 2019 2:17 AM