Reputation:
I have a website where users can upload images (part of some report) and I kinda don't know how to save those images.
I think the best way right now is to download those images into a folder of images.
I never really did something like that and everything I tried isn't working.
Here's my code and markup.
HTML markup: the web
<div class="form-group">
<label asp-for="photoPath" class="control-label"></label>
<input asp-for="photoPath" class="" type="file" onchange="readURL(this);" id="file" accept="image/*" multiple />
<span asp-validation-for="photoPath" class="text-danger"></span>
</div>
<div class="form-group" id="display_image" style="display: none; overflow-y: scroll; height: 400px; width: auto;">
<output id="result" style="overflow-y:scroll; height:400px; width:auto; "></output>
<script>
document.querySelector("#file").addEventListener("change", (e) => {
if (window.File && window.FileReader && window.FileList && window.Blob) {
const files = e.target.files;
const output = document.querySelector("#result");
output.innerHTML = "";
for (let i = 0; i < files.length; i++) {
if (!files[i].type.match("image")) continue;
const picReader = new FileReader();
picReader.addEventListener("load", function (event) {
const picFile = event.target;
console.log(picFile.width)
const div = document.createElement("div");
div.innerHTML = `<img class="form-control" id="thumbnail" src="${picFile.result}" title="${picFile.name}" style="height: 500%;width: 200%;"/>`;
output.appendChild(div);
});
picReader.readAsDataURL(files[i]);
document.getElementById('display_image').setAttribute("style", "display:inline;width:auto");
}
} else {
alert("Your browser does not support File API");
}
});
</script>
C# : model class
public class ReportModel
{
/*
Web stuff
*/
[DisplayName("Add photo")]
public List<string> photoPath { get; set; }
/*
More web stuff
*/
}
Upvotes: 0
Views: 1187
Reputation: 49329
Well, we need more details as to how and where you plan to save the files.
Assuming a webforms app?
Then probably better to start using asp.net controls. They work MUCH better with your code behind.
So, say this simple markup:
<div id="MyUpLoadArea" runat="server">
<asp:FileUpload ID="FileUpLoad1" runat="server" onchange="ShowImagePreview(this);"
AllowMultiple="True" accept="image/*" style="float:left" />
<asp:Image ID="ImgPrv" Width="160px" runat="server" style="float:left"/>
<div style="clear:both;height:20px"></div>
<asp:Button ID="cmdUpLoad" runat="server" Text="Up-Load" CssClass="btn" OnClick="cmdUpLoad_Click" />
<script>
function ShowImagePreview(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#<%=ImgPrv.ClientID%>').prop('src', e.target.result)
};
reader.readAsDataURL(input.files[0]);
}
}
</script>
</div>
So, when we select say 4 files, it displays the first one, and we have this:
So, in above, we have a standard asp.net button we have to click to up-load the files.
The code for that can say be this:
protected void cmdUpLoad_Click(object sender, EventArgs e)
{
string strSQL = "";
SqlCommand cmdSQL;
foreach (HttpPostedFile OneFile in FileUpLoad1.PostedFiles)
{
string strSaveFile = Server.MapPath("~/UpLoadFiles/");
strSaveFile += OneFile.FileName;
OneFile.SaveAs(strSaveFile);
// now add this row to data base
strSQL = "INSERT INTO MyUpLoadFiles (FileName, Size, UpLoadTime, User_ID, SavePath) " +
"VALUES (@FileName, @Size, @UpLoadTime, @User_ID, @SavePath)";
cmdSQL = new SqlCommand(strSQL);
cmdSQL.Parameters.Add("@FileName", SqlDbType.NVarChar).Value = OneFile.FileName;
cmdSQL.Parameters.Add("@Size", SqlDbType.Int).Value = OneFile.ContentLength;
cmdSQL.Parameters.Add("@UpLoadTime", SqlDbType.DateTime).Value = DateTime.Now;
cmdSQL.Parameters.Add("@User_ID", SqlDbType.Int).Value = Session["User_ID"];
cmdSQL.Parameters.Add("@SavePath", SqlDbType.NVarChar).Value = "~/UpLoadFiles/" + OneFile.FileName;
General.MyRstE(cmdSQL);
}
// ALL files saved, display the grid of up-loaded files
strSQL = @"SELECT * FROM MyUpLoadFiles
WHERE User_ID = " + Session["User_ID"].ToString() +
" ORDER BY UpLoadTime DESC ";
cmdSQL = new SqlCommand(strSQL);
DataTable rstFiles = General.MyRstP(cmdSQL);
GridView1.DataSource = rstFiles;
GridView1.DataBind();
MyUpLoadArea.Style.Add("display", "none"); // hide up-load area
MyFileView.Style.Add("display", "normal"); // show file grid
}
so, we send/save all files to the folder MyUpLoadFiles.
We save each file into a database - so we can list them out later, and show ONLY the one users file(s).
So, right below the above div and markup, I have a gridview, like this:
<div id="MyFileView" runat="server">
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns = "False" ShowHeaderWhenEmpty="true" CssClass="table"
width="50%" >
<Columns>
<asp:BoundField DataField="FileName" HeaderText="FileName" />
<asp:BoundField DataField="UpLoadTime" HeaderText="UpLoaded" />
<asp:TemplateField HeaderText="Preview" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:Image ID="Image1" runat="server" width="120px"
ImageUrl = '<% # Eval("SavePath") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Download" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdDownLoad" runat="server" Text="Download" CssClass="btn" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
So, now when I hit up-load button, I get/see this:
We of course need to wire up a event for the download button.
Say, this:
<asp:Button ID="cmdDownLoad" runat="server" Text="Download" CssClass="btn"
OnClick="cmdDownLoad_Click" />
And that code could be:
protected void cmdDownLoad_Click(object sender, EventArgs e)
{
Button myBut = sender as Button;
GridViewRow gRow = myBut.NamingContainer as GridViewRow;
string strFileOnly = gRow.Cells[0].Text;
string strFile = "";
strFile = Server.MapPath(@"~/UpLoadFiles/" + strFileOnly);
string sMineType = MimeMapping.GetMimeMapping(strFileOnly);
Response.ContentType = sMineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + strFileOnly);
Response.TransmitFile(strFile);
Response.End();
}
I also have two helper routines MyRstP and MyRstE - they are just some general code routines I have (became VERY tired of typing code over and over to get a simple conneciton string setup, and then execute some code to return a table, or to execute some sql code. So, those two routines were this:
public static DataTable MyRstP(SqlCommand cmdSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
public static void MyRstE(SqlCommand cmdSQL)
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
cmdSQL.ExecuteNonQuery();
}
}
}
Not really much important - but the above two routines are handy, and thus I don't type that code over and over for simple and general data operations.
Upvotes: 1