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);
Related
I have two questions:
1.When i use postman to upload an image, for example when i browse 15.jpg, it generates something like nDt3Vxjca/15.jpg in value column link
what is nDt3Vxjca.
public async Task<IActionResult> Upload([FromForm] IFormFileViewModel request)
{
var requestContent = new MultipartFormDataContent();
if (request.image!= null)
{
byte[] data;
using (var br = new BinaryReader(request.image.OpenReadStream()))
{
data = br.ReadBytes((int)request.image.OpenReadStream().Length);
}
ByteArrayContent bytes = new ByteArrayContent(data);
requestContent.Add(bytes, "image", request.image.FileName);
};
var client = _httpClientFactory.CreateClient();
string clientID = "abcdefg";
client.DefaultRequestHeaders.Add("Authorization", "Client-ID " + clientID);
var response = await client.PostAsync("https://api.imgur.com/3/upload", requestContent);
return Ok();
}
I copy a some lines of code to convert IformFile to binary. It still manages to upload the image but it doesn't point to my account, it returns something like this:
{"status":200,"success":true,"data":{"id":"I5oGuBd","deletehash":"qVwP3BONUUU9dr7","account_id":null,"account_url":null,"ad_type":null
account_id and account_url is null, Did i make mistake somewhere?
I'm trying to resize imagine with System.Drawing but im taking that file as IFormFile and when i use the System.Drawing its just keep warning me to about that : cannot implicitly convert type 'System.Drawing.Bitmap' to 'Microsoft.AspNetCore.Http.IFormFile' . I need to resize those photos and save them as IFormFile but i dont know how to do that.
public Task<IFormFile> ResizeImagine300x300(IFormFile file)
{
Image image = Image.FromStream(file.OpenReadStream(), true, true);
var newImage = new Bitmap(1024, 768);
using (var g = Graphics.FromImage(newImage))
{
g.DrawImage(image, 0, 0, 1024, 768);
};
return newImage;//the point where i get the error
}
Is it possible to do it in my way?
If its not possible, then which way i should follow?
Thanks for any suggestion
Edit: I wanna return as a IFormFile because i have a method which is uploading those files to my database. here is my method :
public async Task<FileRepo> FileUploadToDatabase(List<IFormFile> files)
{
foreach (var file in files)
{
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var fileExtension = Path.GetExtension(file.FileName);
_fileRepo = new FileRepo
{
FileName = fileName,
FileExtension = fileExtension,
FileType = file.ContentType,
CreatedDate= DateTime.Now
};
using (var dataStream = new MemoryStream())
{
await file.CopyToAsync(dataStream);
_fileRepo.FileData = dataStream.ToArray();
}
}
return _fileRepo;
}
After that I'm uploading that _fileRepo variable to my database like that :
var File = _fileUploader.FileUploadToDatabase(files);
var FileResult = File.Result;
FileResult.ProductID = ProductID;
_unitOfWorkFR.RepositoryFileRepo.Create(FileResult);
Suppose I have sample Upload file method like this in POStFile.aspx.
This method POST file (upload file) to http WEBDAV url.
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
log.Debug(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try {
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
} catch(Exception ex) {
log.Error("Error uploading file", ex);
if(wresp != null) {
wresp.Close();
wresp = null;
}
} finally {
wr = null;
}
}
From here
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
HttpUploadFile("http://your.server.com/upload",
#"C:\test\test.jpg", "file", "image/jpeg", nvc);
Question 1 : Shouldn't the url should be like "http://your.server.com/upload.aspx" instead of "http://your.server.com/upload"
If I give url like "http://your.server.com/upload" then i get 405 error method not found.
So it should point to any page.
Question 2 : How should I receive the post and save the file in upload.aspx.
Can the file directly uploaded to remote server without any receiving
page ?
This question was about "File transfer to WEBDAV http URL using or POST or PUT method"
Above is sample POST method.Similarly there can by PUT method which is little different from POST method.
Question 1 : Shouldn't the url should be like "http://your.server.com/upload.aspx" instead of "http://your.server.com/upload"
For novice man like me, main confusion is URL.It entirely depend upon "How WEBDAV server want to receive POST or PUT method ?"
I think for POST method ,there should be one receiving page which accept file and other parameters from POSTfile page and save the file to disk.
I don't know about .net code but WEB API has inbuilt feature which can parse data like "multipart/form-data; boundary=---------------------------8d60ff73d4553cc"
Below code is just sample code,
[HttpPost]
public async Task<FileUploadDetails> Post()
{
// file path
var fileuploadPath = HttpContext.Current.Server.MapPath("~/UploadedFiles");
////
var multiFormDataStreamProvider = new MultiFileUploadProvider(fileuploadPath);
// Read the MIME multipart asynchronously
await Request.Content.ReadAsMultipartAsync(multiFormDataStreamProvider);
string uploadingFileName = multiFormDataStreamProvider
.FileData.Select(x => x.LocalFileName).FirstOrDefault();
// Files
//
foreach (MultipartFileData file in multiFormDataStreamProvider.FileData)
{
Debug.WriteLine(file.Headers.ContentDisposition.FileName);
Debug.WriteLine("File path: " + file.LocalFileName);
}
// Form data
//
foreach (var key in multiFormDataStreamProvider.FormData.AllKeys)
{
foreach (var val in multiFormDataStreamProvider.FormData.GetValues(key))
{
Debug.WriteLine(string.Format("{0}: {1}", key, val));
}
}
//Create response
return new FileUploadDetails
{
FilePath = uploadingFileName,
FileName = Path.GetFileName(uploadingFileName),
FileLength = new FileInfo(uploadingFileName).Length,
FileCreatedTime = DateTime.Now.ToLongDateString()
};
return null;
}
So url in POSTFile.aspx page should point to API method in this case,
"http://your.server.com/api/fileUpload"
where fileUpload is api controller name.
If you are using HTTP PUT method then
i) you want to receive it in pro grammatically handle it.Write PUT method similar to POST method in api class.
ii) you want to directly save the file to folder using PUT method.
so URL in this case can be,
"http://your.server.com/Imagefolder"
Yes this can be done with extra IIS setting.
Create virtual directory in Target folder,beside few other thing.
I need to display mht file stored in zip archive in frame on the page
<iframe src="#Url.Action("LoadInstrucion","Pharmacy", new {id= Model.Instrukciya })"></iframe>
Action in MVC Controller returning file
public ActionResult LoadInstrucion(string id)
{
var bytes = InstructionsLoader.LoadInstrucion(id);
return File(bytes, "multipart/related");
}
Action for getting byte array from file
public static byte[] LoadInstrucion(string zipFileName)
{
string zipfilePath = $#"{HttpContext.Current.Request.PhysicalApplicationPath}Content\inst\{zipFileName}.zip";
if (File.Exists(zipfilePath))
{
using (var zipStream = new FileStream(zipfilePath, FileMode.Open))
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Read))
{
if (archive.Entries.Count > 0)
{
var file = archive.Entries[0];
var stream = file.Open();
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
}
}
return new byte[0];
}
If I navigate to Url I see the requested mht file, but it is not displayed in iframe. In Dev console I get warning:
Attempted to load a multipart archive into an subframe
I am using a filestream to receive a large file in my controller. codes below:
[HttpPost]
public JsonResult Create(string qqfile, Attachment attachment)
{
Stream inputStream = HttpContext.Request.InputStream;
string fullName = ingestPath + Path.GetFileName(qqfile);
using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write))
{
try
{
var buffer = new byte[1024];
int l = inputStream.Read(buffer, 0, 1024);
while (l > 0)
{
fs.Write(buffer, 0, l);
l = inputStream.Read(buffer, 0, 1024);
}
return Json(new {success = "true"});
}
catch (Exception)
{
return Json(new {success = "false"});
}
finally
{
inputStream.Flush();
inputStream.Close();
fs.Flush();
fs.Close();
}
}
}
And in my page ajax method, I add a button to cancel the file uploading and delete the unfinished file from disk. The ajax request to the action named "Cancel":
[HttpPost]
public JsonResult Cancel(string filename)
{
string localName = HttpUtility.UrlDecode(filename);
string fullName = ingestPath + Path.GetFileName(localName);
if (System.IO.File.Exists(fullName))
{
System.IO.File.Delete(fullName);
}
return Json(new {cancle = true});
}
The problem is: the file can not delete, and the exception message is
the process cannot access the file 'e:\tempdata\filename_xxx.xxx'because it is being used by another process.
I think it is because that ,the filestream of this file is not closed. How can I close this filestream and delete the file in my 'Cancel' action?
--
OH! I found a method to resolve it now.
using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write))
It is to simple, just declaration a fileshare property: FileShare.Delete
using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write, FileShare.Delete))
I spent 4 hours to google and debug and test and try to resolve it. Just 10 mins after I asked stackoverflow, I got the answer by myself. Interesting! And hope it is useful to someone too.
You could put that file stream in a session then use that session in your cancel action to close the stream.