I'm uploading an image to my site using the following code,
The Image uploading just fine but, how ever
I need to fix the following things :
-I'm getting this kind of Url
C:\Users\Me\Documents\Visual Studio 2013\Projects\Wow\WowMvc5\WowMvc5\images\gallery\Picture 022.jpg,
Instead of relevant folder Url
-I thing in order to avoid an error of 2 images this the same name it would be better to create a folder under images for each image (or any better idea )
Thank you for your time
public async Task<ActionResult> Create([Bind(Include = "TakeAwayId,TakeAwayName,description,Price,DishUrl,quantity,DishesAmount,GenreId")] TakeAway takeaway)
{
var path = Server.MapPath("~/Images/gallery/");
foreach (string item in Request.Files)
{
HttpPostedFileBase file = Request.Files[item];
if (file.ContentLength == 0)
{
continue;
}
string SavedFileName = System.IO.Path.GetFileName(file.FileName);
SavedFileName = Server.MapPath
("~" + "/images/gallery/" + SavedFileName);
file.SaveAs(SavedFileName);
takeaway.DishUrl = SavedFileName;
}
if (ModelState.IsValid)
{
db.takeaway.Add(takeaway);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.GenreId = new SelectList(db.genre, "GenreId", "GenreName", takeaway.GenreId);
return View(takeaway);
}
What I would do is name and save each picture using a HashCode.
By definition, It's very improbable that 2 different strings, when transformed using a hash algorithm, will have the same output. Just to be sure, add a random string to the original name of the image.
string newName = (oldName + random).GetHashCode().ToString()
filename_1.jpg
where cnt is incremental count
if(file.exists()
{
string cnt = file.split("");
String newFileName = filename+""+(cnt+1)+".jpg";
}
Related
I'm loading images which are store in the database and I want to upload them to the serverpath which is in wwwroot folder.
byte[] imageData= //Loading image from sql server
string strWebPath = _hostingEnvironment.WebRootPath + "\\img\\+"This is where I want to upload that image"";
How can I upload that image into wwwroot/img folder
Storing image datas in the database is not the best way.
Anyway, if you have your image data in a byte array, you can store it anywhere using a filestream.
You need to add : using System.IO;
byte[] imageData = ...//Loading image from sql server
string strWebPath = _hostingEnvironment.WebRootPath + "\\img\\myImageName.png"; //yourImageName.Extension;
//You may have to change the FileMode.Create according the image names if, unique etc.
using (FileStream fs = new FileStream(strWebPath, FileMode.Create))
{
//Takes a byte array, writes to the disk from the given index until the given length.
fs.Write(imageData, 0, imageData.Length);
fs.Flush();
}
I hope this helps.
In most cases, files are stored in the database as byte[]. So you can use this method to achieve it.
FileModel:
public class AppFile
{
public int Id { get; set; }
public string FileName { get; set; }
public byte[] Content { get; set; }
}
Method:
public async Task Uploadfilefromdb(int id)
{
//select file by id
var result =await _dbcontext.File.FirstOrDefaultAsync(x => x.Id == id);
var fileName = Path.GetFileName(result.FileName);
var filePath = Path.Combine(Directory.GetCurrentDirectory(), #"wwwroot\images",fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
//convert byte[] to IformFile
var stream = new MemoryStream(result.Content);
IFormFile file = new FormFile(stream, 0, result.Content.Length, "name", fileName);
await file.CopyToAsync(fileStream);
}
}
Demo:
After I use this method, image has been uploaded from database to wwwroot.
I have a controller action that creates a zip file and sends back to user for download. The problem is that the zip file gets created but it is empty. Somehow it's not writing the image files to the MemoryStream. I wonder what I am missing. If I write the zip file to the disk everything will work as expected, but I'd rather not save files to the disk if I can avoid it. This is what I have tried using dotnetzip:
public ActionResult DownloadGraphs()
{
var state = Session["State"];
using (ZipFile zip = new ZipFile())
{
if (state == "IA")
{
zip.AddFile(Server.MapPath("~/Content/DataVizByState/FallGraphs/Watermarked/Fall_IA.jpg"), "");
zip.AddFile(Server.MapPath("~/Content/DataVizByState/SpringGraphs/Watermarked/Spring_IA.jpg"), "");
}
MemoryStream output = new MemoryStream();
zip.Save(output);
output.Seek(0, SeekOrigin.Begin);
var fileName = state + "Graphs.zip";
return File(output, "application/zip", fileName);
}
}
This forces download in the view based on click of a button:
$('#graphDwnldBtn').click(function (evt) {
window.location = '#Url.Action("DownloadGraphs", "DataSharing")';
})
Do I need to use StreamWriter or Reader or something? This is the first time I have ever attempted something like this and it's been cobbled together by reading various stackoverflow posts...
Dumb mistakes: Session["State"] is an object, so the state variable was coming out as object instead of a string like I need it to be for my conditional statement to evaluate correctly. I cast state to a string to fix it. Fixed code:
public ActionResult DownloadGraphs()
{
var state = Session["State"].ToString();
using (ZipFile zip = new ZipFile())
{
if (state == "IA")
{
zip.AddFile(Server.MapPath("~/Content/DataVizByState/FallGraphs/Watermarked/Fall_IA.jpg"), "");
zip.AddFile(Server.MapPath("~/Content/DataVizByState/SpringGraphs/Watermarked/Spring_IA.jpg"), "");
}
MemoryStream output = new MemoryStream();
zip.Save(output);
output.Seek(0, SeekOrigin.Begin);
var fileName = state + "Graphs.zip";
return File(output, "application/zip", fileName);
}
}
public ActionResult Import(HttpPostedFileBase currencyConversionsFile)
{
string filename = "CurrencyConversion Upload_" + DateTime.Now.ToString("dd-MM-yyyy") + ".csv";
string folderPath = Server.MapPath("~/Files/");
string filePath = Server.MapPath("~/Files/" + filename);
currencyConversionsFile.SaveAs(filePath);
string[] csvData = System.IO.File.ReadAllLines(filePath);
//the later code isn't show here
}
I know the usual way to convert httppostedfilebase to String array, which will store the file in the server first, then read the data from the server. Is there anyway to get the string array directly from the httppostedfilebase with out store the file into the server?
Well you can read your file line by line from Stream like this:
List<string> csvData = new List<string>();
using (System.IO.StreamReader reader = new System.IO.StreamReader(currencyConversionsFile.InputStream))
{
while (!reader.EndOfStream)
{
csvData.Add(reader.ReadLine());
}
}
From another thread addressing the same issue, this answer helped me get the posted file to a string -
https://stackoverflow.com/a/40304761/5333178
To quote,
string result = string.Empty;
using (BinaryReader b = new BinaryReader(file.InputStream))
{
byte[] binData = b.ReadBytes(file.ContentLength);
result = System.Text.Encoding.UTF8.GetString(binData);
}
Splitting the string into an array -
string[] csvData = new string[] { };
csvData = result.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
I'm getting an image from a base64 string, stored in a datatable. This string pulls successfully and is a valid base64 string, as I have tested it on free image decode websites and it decodes it back to the image I originally uploaded.
Now, I am trying to write the image to a file and no matter what I try, it fails to create the image file properly. The image only shows if I return it to a View as File(imageBytes, "image/jpeg")
Here is my code:
string imagepath = Path.Combine(Server.MapPath("~/Content"), client.ClientId + "_task" + task.TaskId + "_TaskReport.jpg");
byte[] imageBytes = Convert.FromBase64String(myDataTable.Rows[0].ItemArray[1].ToString()); // this works elsewhere, but for some reason only when returning the image to the view as a FileResult
using (var imageFile = new FileStream(imagepath, FileMode.Create))
{
imageFile.Write(imageBytes, 0, imageBytes.Length); // this line creates the bad image!
imageFile.Flush();
}
What is wrong with my code? Why does it work with the mvc FileResult and not when converting to an image?
Try this to write file
byte[] b= //Your Image File in bytes;
System.IO.File.WriteAllBytes(#"c:\data.jpg", b)
Try this,
[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
try
{
if (file != null && file.ContentLength > 0)
{
System.IO.MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
byte[] data = target.ToArray();
}
}
catch (Exception ex)
{
throw;
}
return View("Index",model);
}
return View();
}
I'm adding a row to Videos and then I want to use that same ID as the video's physical filename. so I need to add the row without the filename, and then use the ID I get, then update that row with the filename. I'm just now sure how to do that.
public ActionResult UpVideo(Report Report, string VideoName, HttpPostedFileBase file)
{
Video v = new Video();
v.Name = VideoName;
v.Report = Report;
db.Videos.Add(v);
var filename = v.ID + "." + Path.GetExtension(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/video_uploads"), filename);
file.SaveAs(path);
v.FileName = filename;
//** update Row here with filename
db.SaveChanges();
//** redirect back to Report Details (need to figure out how do do this too)
return RedirectToAction(Report);
}
Assuming that you have an auto incrementing primary key for ID in your database, you need to call save changes before referencing the ID property. You have to save the entity to the database so that the ID can be assigned.
public ActionResult UpVideo(Report Report, string VideoName, HttpPostedFileBase file)
{
Video v = new Video();
v.Name = VideoName;
v.Report = Report;
db.Videos.Add(v);
db.SaveChanges();
var filename = v.ID + "." + Path.GetExtension(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/video_uploads"), filename);
file.SaveAs(path);
v.FileName = filename;
db.SaveChanges();
//** redirect back to Report Details (need to figure out how do do this too)
return RedirectToAction(Report);
}
Since 'filename' is only a combination of the Id and the file extension, why not just save the file extension and do the concatenation when you need to reference the video. This would reduce your calls to the database back down to one and save a little on DB storage
public ActionResult UpVideo(Report Report, string VideoName, HttpPostedFileBase file)
{
Video v = new Video();
v.Name = VideoName;
v.FileName = Path.GetExtension(file.FileName);
v.Report = Report;
db.Videos.Add(v);
db.SaveChanges();
var filename = v.ID + "." + v.FileName;
var path = Path.Combine(Server.MapPath("~/App_Data/video_uploads"), filename);
file.SaveAs(path);
//** redirect back to Report Details (need to figure out how do do this too)
return RedirectToAction(Report);
}