I need a function which checks if the HttpPostedFileBase is a word document. I don't want to check against file extension because that can be changed by the user.
I tried to read the Header information of the binary data, which starts with PK (for example, PDF files starts with %PDF), but i don't know if i can rely upon that.
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
string header = null;
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
char[] buffer = new char[5];
sr.Read(buffer, 0, 4);
header =
string.Format("{0}{1}{2}{3}{4}", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]);
}
}
if (header.StartsWith("%PDF"))
{
// PDF Document
}
if (header.StartsWith("PK"))
{
// Microsoft Word Document ?
}
return Json(new { }, JsonRequestBehavior.AllowGet);
}
The first two letters of a word document (DOCX) are PK because a DOCX file is actually a PKZip file; so no, this is not reliable.
The ForensicsWiki page here may help:
http://www.forensicswiki.org/wiki/Word_Document_%28DOC%29
and
http://www.forensicswiki.org/wiki/DOCX
Related
I am using Xamarin essential using Multipicker while choosing corrupted video its also selected in the Media list when upload time it showing setdatasource failed. How to detect when choosing at time video is corrupted or any other option
result = await Xamarin.Essentials.FilePicker.PickMultipleAsync(new Xamarin.Essentials.PickOptions
{
FileTypes = Xamarin.Essentials.FilePickerFileType.Videos,
PickerTitle = "Please pick a videos"
});
If you want to detect corrupted video while picking video, you could compare the MD5 value.
But on this way, you need to have correct the MD5 value. For example, i put the correct MD5 value in .txt file of Assets folder and then get the MD5 value when picking video and compare it.
public void Compare()
{
string content;
AssetManager asset1 = Android.App.Application.Context.Assets;
using (StreamReader sr = new StreamReader(asset1.Open("AboutAssets.txt")))
{
content = sr.ReadToEnd();
}
var InPuthash= GetMd5Hash(content);
string hash = "sfsgDGDgds";
var result = VerifyMd5Hash(InPuthash, hash);
}
static string GetMd5Hash(string input)
{
using (MD5 md5Hash = MD5.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
// Verify a hash against a string.
static bool VerifyMd5Hash(string input, string hash)
{
// Hash the input.
string hashOfInput = GetMd5Hash(input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
return 0 == comparer.Compare(hashOfInput, hash);
}
i want to download varbinary stored in database as a file. I am able to download the file, however all the file that downloaded from my application are unable to open. I noticed that i upload pdf file with size 200 kb. But when i download that file, its only return 30 byte.
Here is the code:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Upload(Upload model, HttpPostedFileBase uploadFile, String random_number, String rcf_number)
{
var db = new RCFOnlineEntities();
if(uploadFile != null)
{
byte[] bytes;
using (BinaryReader br = new BinaryReader(uploadFile.InputStream))
{
bytes = br.ReadBytes(uploadFile.ContentLength);
}
model.file_base6 = bytes;
model.file_ext = uploadFile.ContentType;
model.file_name = uploadFile.FileName;
model.rcfnumber = rcf_number;
model.randomnumber = random_number;
}
db.Uploads.Add(model);
db.SaveChanges();
return RedirectToAction("Edit", "GetRCFOnline", new { random_number = random_number });
}
[HttpGet]
public FileResult DownLoadFile(int id, String random_number)
{
List<Upload> ObjFiles = GetUploadClasses(random_number);
var FileById = (from FC in ObjFiles
where FC.file_id.Equals(id)
select new { FC.file_name, FC.file_base6 , FC.file_ext}).ToList().FirstOrDefault();
return File(FileById.file_base6, FileById.file_ext, FileById.file_name);
}
Could you tell me where is the error within my code ?
Solution-1:
Use uploadFile.InputStream.Length instead uploadFile.ContentLength for correct upload file size i.e.
using (BinaryReader br = new BinaryReader(uploadFile.InputStream))
{
bytes = br.ReadBytes(uploadFile.InputStream.Length);
}
Solution-2:
If BinaryReader is not a fixed requirement then use below solution to get uploaded file's bytes i.e.
byte[] bytes = new byte[uploadFile.InputStream.Length];
uploadFile.InputStream.Read(bytes, 0, bytes.Length);
I have been looking into phantomJS and looks like it could be a great tool to use generating PDFs. I wonder if anyone have successfully used it for their .NET applications.
My specific question is: how would you use modules like rasterize.js on the server, receive requests and send back generated pdfs as a response.
My general question is: is there any best practice for using phantomJS with .NET Applications. What would be the best way to achieve it?
I am fairly new in .NET World and I would appreciate the more detailed answers. Thanks everyone. :)
I don't know about best practices, but, I'm using phantomJS with no problems with the following code.
public ActionResult DownloadStatement(int id)
{
string serverPath = HttpContext.Server.MapPath("~/Phantomjs/");
string filename = DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".pdf";
new Thread(new ParameterizedThreadStart(x =>
{
ExecuteCommand("cd " + serverPath + #" & phantomjs rasterize.js http://localhost:8080/filetopdf/" + id.ToString() + " " + filename + #" ""A4""");
})).Start();
var filePath = Path.Combine(HttpContext.Server.MapPath("~/Phantomjs/"), filename);
var stream = new MemoryStream();
byte[] bytes = DoWhile(filePath);
return File(bytes, "application/pdf", filename);
}
private void ExecuteCommand(string Command)
{
try
{
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;
Process = Process.Start(ProcessInfo);
}
catch { }
}
public ViewResult FileToPDF(int id)
{
var viewModel = file.Get(id);
return View(viewModel);
}
private byte[] DoWhile(string filePath)
{
byte[] bytes = new byte[0];
bool fail = true;
while (fail)
{
try
{
using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
}
fail = false;
}
catch
{
Thread.Sleep(1000);
}
}
System.IO.File.Delete(filePath);
return bytes;
}
Here is the action flow:
The user clicks on a link to DownloadStatement Action. Inside there, a new Thread is created to call the ExecuteCommand method.
The ExecuteCommand method is responsible to call phantomJS. The string passed as an argument do the following.
Go to the location where the phantomJS app is and, after that, call rasterize.js with an URL, the filename to be created and a print format. (More about rasterize here).
In my case, what I really want to print is the content delivered by the action filetoupload. It's a simple action that returns a simple view. PhantomJS will call the URL passed as parameter and do all the magic.
While phantomJS is still creating the file, (I guess) I can not return the request made by the client. And that is why I used the DoWhile method. It will hold the request until the file is created by phantomJS and loaded by the app to the request.
If you're open to using NReco.PhantomJS, which provides a .NET wrapper for PhantomJS, you can do this very succinctly.
public async Task<ActionResult> DownloadPdf() {
var phantomJS = new PhantomJS();
try {
var temp = Path.Combine(Path.GetTempPath(),
Path.ChangeExtension(Path.GetRandomFileName(), "pdf")); //must end in .pdf
try {
await phantomJS.RunAsync(HttpContext.Server.MapPath("~/Scripts/rasterize.js"),
new[] { "https://www.google.com", temp });
return File(System.IO.File.ReadAllBytes(temp), "application/pdf");
}
finally {
System.IO.File.Delete(temp);
}
}
finally {
phantomJS.Abort();
}
}
Here's some very basic code to generate a PDF using Phantom.JS but you can find more information here: https://buttercms.com/blog/generating-pdfs-with-node
var webPage = require('webpage');
var page = webPage.create();
page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.google.com", function start(status) {
page.render('google_home.pdf, {format: 'pdf', quality: '100'});
phantom.exit();
});
I added text file to my web project. Right click and clicking on properties
menu I choose ,Build Action -> Resource.
How can I retrieve the content of the file in my code behind page.
I try this but I received stream null
internal string GetFromResources(string resourceName)
{
Assembly assem = this.GetType().Assembly;
using (Stream stream = assem.GetManifestResourceStream(resourceName))
{
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
But it's not working.
Please help
Try changing the Build Action to Embedded Resource and make sure that the resource name contains the namespace. i.e.
MyProjectNamespace.MyTextFileName.txt
If your file is in a sub folder then use:
MyProjectNamespace.SubFolderName.MyTextFileName.txt
I solved it, below are the steps that I took.
First of all I defined text file as embedded resource.
Second problem was that I did not added assembly name space to the text file.
So I changed the function and added namespace
internal string GetFromResources(string resourceName)
{
Assembly assem = this.GetType().Assembly;
**List<string> listNameSpaces = assem.GetTypes().Select(t => t.Namespace).Distinct().ToList<string>();**
foreach (string ns in listNameSpaces)
{
**string nsResourceName = ns + "." + resourceName;**
using (Stream stream = assem.GetManifestResourceStream(nsResourceName))
{
if (stream != null)
{
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
}
return string.Empty;
}
I m using Opendialogbox to read the file. Then stored the file in byte[] array.
file --> byte []
byte[] --> stored on SQL AZure in varbinary(max) field.
Here is my code:
OpenFileDialog ofd = new OpenFileDialog();
if ((bool)ofd.ShowDialog())
{
FileStream fileStream = ofd.File.OpenRead());
byte[] buffer = new byte[fileStream.Length];
int read = 0;
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
do
{
read = binaryReader.Read(buffer, 0, Convert.ToInt32(fileStream.Length));
// Stored the File in byte[] Array buffer
} while (read > 0);
}
}
Now I want to convert this byte array to the original file (like .doc,.txt,jpeg). i know the extension in which file is to be convert.
SQL AZure ---> byte[] // done
byte[] ---> to original file. // Problem
Please give solution to download the file.
One way - not necessarily the best - is as follows:
using (MemoryStream ms = new MemoryStream(theBytes))
{
using (FileStream fs = new FileStream(string.Format("C:\\tempfile.{0}", theExtension)))
{
ms.WriteTo(fs);
}
}
namespace FileSaveDialogDemo
{
public partial class MainPage : UserControl
{
#region Fields
SaveFileDialog dialog= new SaveFileDialog();
#endregion
#region Constructors
public MainPage()
{
InitializeComponent();
this.dialog = new SaveFileDialog();
try
{
this.dialog.DefaultExt = ".txt";
this.dialog.Filter = "Text Files|*.txt|Log Files|*.log|All Files|*.*";
this.dialog.FilterIndex = 2;
}
catch ( Exception ex )
{
this.tblError.Text = "Error configuring SaveFileDialog: " + ex.Message;
}
}
#endregion
private void btnSaveFile_Click( object sender, RoutedEventArgs e )
{
bool? dialogResult = this.dialog.ShowDialog();
if ( dialogResult == true )
{
try
{
byte[] fileBytes; // your varbinary file from database
using (Stream fs = (Stream)dialog.OpenFile())
{
fs.Write(fileBytes, 0, fileBytes.Length);
fs.Close();
lblMsg.Content = "File successfully saved!";
}
}
catch ( Exception ex )
{
this.tblError.Text = "Error calling service: " + ex.Message;
}
}
} // End of Function
}// End of MainPage class
}
It seems the issue you have has probably nothing to do with saving a binary file; it is more likely a basic security issue. Try saving to a path on which you have programmatic write access. For example, try saving to your My Documents directory instead of C:. Try using the Environment.SpecialFolder enumeration like this, and append the file name + extension.
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
You have a number of other ways to work around this issue, including starting Visual Studio in Elevated Mode (run as Administrator), and/or allow "Everyone" write access to your C:\ drive. But I wouldn't recommend these techniques necessarily; consider saving to a folder where the security settings are lower than c:\, such as My Documents.