Actually I load the picture on the server. But once we do this, the page refreshes. My goal is to do this without refreshing the page. How can I do that? Is there anyone who can help?
In the code below I write onsubmit = "return false" in the form. But the picture is not uploaded to the server because the page is not refresh in this way.
VIEW
#using (Html.BeginForm("create_conference", "Home", FormMethod.Post, new { enctype = "multipart/form-data", id = "registerFormValidation", onsubmit = "return false" }))
{
<div class="form-group">
<div class="input-group">
<span class="btn btn-default btn-wd btn-info btn-fill btn-file input-group-addon">
<i class="fa fa-image"></i> <input type="file" name="file" id="imgInp" accept="image/*">
</span>
<input type="text" class="form-control" readonly id="image-path" value="">
</div>
</div>
<div id="enter-room-name">
<div class="form-group">
<input type="text" placeholder="Enter Name of Room" class="form-control" required="true" id="room-name" autocomplete="false" style="text-transform:uppercase">
</div>
<button type="submit" name="add-room-submit" class="btn btn-info btn-round btn-wd">Save</button>
</div>
}
CONTROLLER
[HttpPost]
public ActionResult create_conference(HttpPostedFileBase file)
{
var path = "";
if (file != null)
{
if (file.ContentLength > 0)
{
//for checking uploaded file is image or not
if(Path.GetExtension(file.FileName).ToLower()==".jpg"
|| Path.GetExtension(file.FileName).ToLower()==".png"
|| Path.GetExtension(file.FileName).ToLower()==".gif"
|| Path.GetExtension(file.FileName).ToLower()==".jpeg")
{
path = Path.Combine(Server.MapPath("~/assets/img/conference-img"), file.FileName);
file.SaveAs(path);
ViewBag.UploadSuccess = true;
}
}
}
return View();
//return Redirect("rooms");
}
Don't read it as base64 using the fileReader or using a iframe...
Simply turn the form element into a FormData and send that to the server.
A good idea is not trying to specify method/url in the javascript keep it as general as possible and have the html markup do what it was meant to do (defining things) then you can use this function for more forms and it got a more graceful degration if javascript where turned of
function turnFormToAjax(evt) {
evt.preventDefault()
var form = evt.target
var fd = new FormData(fd)
fetch(form.target, {method: form.method, body: fd})
.then(function(res) {
// done uploading
})
}
document.querySelector('form').onsubmit = turnFormToAjax
Convert to base64 and ajax call it. Make sure the backend converts it back to an image file before saving it.
I've done it with jquery in the past.
This is the important part:
I've done it with jquery. This is the important part.
$(document).ready(function() {
$('#imageFile').change(function(evt) {
var files = evt.target.files;
var file = files[0];
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('preview').src = e.target.result;
};
reader.readAsDataURL(file);
// console.log(file.name)
var filename = file.name
console.log(filename);
}
});
make sure filename sends.
You can upload image using iframe, using iframe and ajax image will upload without page refresh.
You can try using my sample.
HTML:
<form id="registerFormValidation" name="registerFormValidation" action="" method="POST" enctype="multipart/form-data" >
<div id="main">
<input name="imgInp" id="imgInp" size="27" type="file" />
<input type="button" name="action" value="Upload" onclick="upload()"/>
<iframe id='my_iframe' name='my_iframe' src="">
</iframe>
</div>
</form>
This is my JS:
function upload()
{
//'my_iframe' is the name of the iframe
document.getElementById('registerFormValidation').target = 'my_iframe';
document.getElementById('registerFormValidation').submit();
}
And For Server side you can use simple Ajax method or Custom method.If you use ajax method then action will be action="javascript:submitForm();" and if you use custom method then you can use your function name.
Related
I have an upload button on my MVC web application which allows a user to upload a file. This file is uploaded onto the system and some async actions are made on this file which may take up to 1/2 minutes. I would like show processing.gif when the users presses the upload button and then hide the .gif when the async actions have finished i.e. when "return View();" has occurred from the HttpPost Upload controller. Can anyone tell me the easiest way to implement this please? I have been messing around with it and can not get it to work correctly. The processing.gif image is currently hidden as you can see from the below code:
The Upload View:
<h4><strong>Upload Survey</strong></h4>
<div>
<p><strong>Upload Surveys in .PDF format</strong></p>
<br />
<form class="btn btn-default" method="post" enctype="multipart/form-data" action="#Url.Action("Upload", "CompletedCamps")">
<div>
<input name="file" type="file" class="btn btn-link" required />
<br />
<button type="submit" class="btn btn-block btn-primary">Import</button>
</div>
</form><img id="loading" src="../../Content/processing.gif" alt="Updating ..." style="display:none" />
</div>
<br />
The Upload Controllers:
[HttpGet]
public ActionResult Upload(int? id)
{
CompletedCamp completedCamp = db.CompletedCamps.Find(id);
return View(completedCamp);
}
[HttpPost]
public async Task<ActionResult> Upload(HttpPostedFileBase file, int? id)
{
CompletedCamp completedCamp = db.CompletedCamps.Find(id);
string filename = Guid.NewGuid() + Path.GetExtension(file.FileName);
string filepath = Server.MapPath(Path.Combine("~/Surveys/", filename));
file.SaveAs(filepath);
await AzureVisionAPI.ExtractToTextFile(filepath);
ParseSurveyText parse1 = new ParseSurveyText();
await Task.Run(() => parse1.ParseTextFile(completedCamp.RollNumber, completedCamp.OfficialSchoolName, completedCamp.Date));
return View();
}
You can use client side code like jquery to register the form submit button so that as soon as form is submitted the loader appears. code would be something like:
$("form#formId").submit(function(){
$("img#loading").show();
});
Make sure to add id attribute with the id which would be used in the jquery code.
Related html should look like:
<form id="formId" class="btn btn-default" method="post"
enctype="multipart/form-data" action="#Url.Action("Upload", "CompletedCamps")">
......
......
</form><img id="loading" src="../../Content/processing.gif"
alt="Updating ..." style="display:none" />
Hope it makes sense and give you idea.
I'm building a custom "Google Forms"-form with a file upload function.
The form uses a custom "Thankyou"-page (see 1st line: iframe).
I've found a file upload script that needs to run in the Google Script environment and it will upload files to my Google Drive.
Now I need to combine this upload script with my custom Google Form.
But I don't know exactly how to achieve this because there actions that need to be combined and the file upload has to be completed first before going to the "Thank you" page.
I've tried to combine it which looks like the code below.
The form:
<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted) { picUploadJs(myForm); }"></iframe>
<form id="myForm" action="https://docs.google.com/forms/d/e/xxx/formResponse" target="hidden_iframe" onsubmit="submitted=true;">
<input placeholder="1234" name="entry.1234" id="user" type="text">
<label for="user">User:</label>
<input name="picToLoad" type="file" />
<div id="status" style="display: none">
Uploading. Please wait...
</div
<button type="submit" name="action">Send</button>
</form>
The upload script:
<script>
function picUploadJs(frmData) {
document.getElementById('status').style.display = 'inline';
google.script.run
.withSuccessHandler(updateOutput)
.processForm(frmData)
};
function updateOutput() {
var outputDiv = document.getElementById('status');
outputDiv.innerHTML = "The File was UPLOADED!";
window.location='https://thankyoupage/';
}
</script>
This now results in:
Form input data is submitted, upload status text appears but nothing happens: "Uploading. Please wait...".
The result should be:
Form input data submit, upload file to drive and redirect to the thankyou page.
EDIT:
Google Script code
function doGet(e) {
return HtmlService.createTemplateFromFile('test')
.evaluate() // evaluate MUST come before setting the Sandbox mode
.setTitle('Name To Appear in Browser Tab')
//.setSandboxMode();//Defaults to IFRAME which is now the only mode available
}
function processForm(theForm) {
var fileBlob = theForm.picToLoad;
Logger.log("fileBlob Name: " + fileBlob.getName())
Logger.log("fileBlob type: " + fileBlob.getContentType())
Logger.log('fileBlob: ' + fileBlob);
var fldrSssn = DriveApp.getFolderById('xxxx');
fldrSssn.createFile(fileBlob);
return true;
}
When you click "Send" button,
Google Form works fine.
document.getElementById('status').style.display = 'inline' works.
Function of processForm(frmData) at Google Apps Script doesn't work.
Function of updateOutput() at Javascript doesn't work.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
Modification points:
In this modification, the file was retrieved using onclick event, while the script for submitting to Google Form is not modified.
The retrieved file is converted to base64 and sent to Google Apps Script.
Modified script:
HTML:
<form id="myForm" action="https://docs.google.com/forms/d/e/xxx/formResponse" target="hidden_iframe" onsubmit="submitted=true;">
<input placeholder="1234" name="entry.1234" id="user" type="text">
<label for="user">User:</label>
<input name="picToLoad" type="file" id="sampleFile" /> <!-- Modified -->
<div id="status" style="display: none">
Uploading. Please wait...
</div>
<button type="submit" name="action" id="sampleId" >Send</button> <!-- Modified -->
</form>
Javascript:
<script>
// Below script was added.
document.getElementById("sampleId").onclick = function(e) {
e.stopPropagation();
e.preventDefault();
var file = document.getElementById("sampleFile").files[0];
const f = new FileReader();
f.onload = (e) => {
const data = e.target.result.split(",");
const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
picUploadJs(obj);
}
f.readAsDataURL(file);
};
function picUploadJs(frmData) {
document.getElementById('status').style.display = 'inline';
google.script.run.withSuccessHandler(updateOutput).processForm(frmData)
};
function updateOutput() {
var outputDiv = document.getElementById('status');
outputDiv.innerHTML = "The File was UPLOADED!";
window.location='https://thankyoupage/';
}
</script>
Google Apps Script:
function processForm(theForm) {
var fileBlob = Utilities.newBlob(Utilities.base64Decode(theForm.data), theForm.mimeType, theForm.fileName);
var fldrSssn = DriveApp.getFolderById('xxxx');
fldrSssn.createFile(fileBlob);
return true;
}
Note:
When the file is selected and click a "Send" button, the file is send to Google Apps Script and is created as a file on Google Drive, while Google Form is submitted. Then updateOutput() at Javascript side is run.
In this modified script, The blob is used. So the maximum size of a file for uploading is 50 MB. Please be careful this.
Edit 1:
At your comment, it was found that When I remove the id=sampleId from the submit button, the Google Form data is submitted correctly. Using this, please test the following modification.
In this modification, id="sampleId" was removed and the event is triggered using the name of element.
HTML:
<form id="myForm" target="hidden_iframe" onsubmit="submitted=true;">
<input placeholder="1234" name="entry.1234" id="user" type="text">
<label for="user">User:</label>
<input name="picToLoad" type="file" id="sampleFile" />
<div id="status" style="display: none">
Uploading. Please wait...
</div>
<button type="submit" name="action">Send</button> <!-- Modified -->
</form>
Javascript:
var button = document.getElementsByName('action')[0]; // Modified
button.onclick = function(e) { // Modified
e.stopPropagation();
e.preventDefault();
var file = document.getElementById("sampleFile").files[0];
const f = new FileReader();
f.onload = (e) => {
const data = e.target.result.split(",");
const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
picUploadJs(obj);
}
f.readAsDataURL(file);
};
Edit 2:
I updated HTML and Javascript. Please confirm it. Google Apps Script is not modified.
HTML:
<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted) { picUploadJs(myForm); }"></iframe>
<form id="myForm" action="https://docs.google.com/forms/d/e/xxx/formResponse" target="hidden_iframe" onsubmit="submitted=true;">
<input placeholder="1234" name="entry.1234" id="user" type="text">
<label for="user">User:</label>
<input name="picToLoad" type="file" id="sampleFile" /> <!-- Modified -->
<div id="status" style="display: none">
Uploading. Please wait...
</div>
<button type="submit" name="action">Send</button>
</form>
Javascript:
<script>
// This function was modified.
function picUploadJs(myForm) {
var file = document.getElementById("sampleFile").files[0];
const f = new FileReader();
f.onload = (e) => {
const data = e.target.result.split(",");
const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
document.getElementById('status').style.display = 'inline';
google.script.run.withSuccessHandler(updateOutput).processForm(obj);
}
f.readAsDataURL(file);
}
function updateOutput() {
var outputDiv = document.getElementById('status');
outputDiv.innerHTML = "The File was UPLOADED!";
window.location='https://thankyoupage/';
}
</script>
I have a simple HTML form like this:
<div class="border-little text-center grey">
<form action="https://www.THIS IS MY URL.php" method="get">
<input name="player" id="player" value="1" class="hidden">
<label for="number">Enter a number</label>
<input type="text" id="number" name="number" placeholder="">
<input type="submit" value="Submit">
</form>
</div>
The operation is as follows:
The player enters a number, and the server answers using a JSON format.
My issue:
When I press "submit" My webpage leaves and redirects to the server page display a JSON formatted answer.
What I want to do:
I want to stay on my page and be able to receive the answer in JSON format and display them below my form instead of being redirected to the server page.
More details:
example of JSON answer I get from the server:
{"guess": "lower"}
I cannot use any kind of JavaScript library so JQuery is forbidden.
you just use ajax method of js
function r_submit() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "https://www.THIS IS MY URL.php", true);
var params = {"player":document.getElementById("player").value};
xhttp.send(params);
xhttp.onload = function() {
alert(xhttp.responseText);
}
}
and execute r_submit() function button when you click button
here your html code will be like
<div class="border-little text-center grey">
<input name="player" id="player" value="1" class="hidden">
<label for="number">Enter a number</label>
<input type="text" id="number" name="number" placeholder="">
<input type="submit" value="Submit" onsubmit='r_submit()'>
</form>
</div>
i've written years ago a simple js part, that allows you to send XHR requests easily. it's a little deprecated but it is a simple template to understand how you CAN go on.
you could modernize it by using webworkers and make it closer to your setup. if you wish i could post an old prototype in JS from me with webworkers and so on (but some names of variables are in german..)
function getElement(inp)
{
return document.getElementById(inp);
}
function put(data,div)
{
getElement(div).innerHTML = data;
}
//information: autoput means: do you wish to write the raw response in a div? [0,1] - when 1 then put the id of the div in var div at the call of the function
function get(url,data,method,autoput,div)
{
var req;
if(window.XMLHttpRequest)
{
req = new XMLHttpRequest();
}
else
{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.onreadystatechange = function()
{
if(req.readyState == 4 && req.status == 200)
{
if(autoput == 1)
{
put(req.responseText, div);
}
}
}
if(method.toLowerCase() == "get")
{
req.open("GET",url+data,true);
req.send();
}
else
{
if(method.toLowerCase() == "post")
{
if(data !== "")
{
req.open("POST", url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.send(data);
}
}
}
}
It's possible to use iframe technique when jQuery is forbidden. Submit the form to the named iframe and wait for onload event. Modified html and js code will look like:
<div class="border-little text-center grey">
<form action="https://www.THIS IS MY URL.php" method="get" target="myframe">
<input name="player" id="player" value="1" class="hidden">
<label for="number">Enter a number</label>
<input type="text" id="number" name="number" placeholder="">
<input type="submit" value="Submit">
</form>
</div>
<iframe id="myframe" name="myframe"></iframe>
<script>
var myframe = document.getElementById("myframe");
myframe.onload = function() {
var iframeDocument = myframe.contentDocument || myframe.contentWindow.document; // get access to DOM inside the iframe
var content = iframeDocument.textContent || iframeDocument.body.textContent; // get text of iframe
var json = JSON.parse(content);
if (json && json.guess) {
// process the json here
alert(json.guess);
}
}
</script>
I am currently uploading a file to the server in Django as follows (For some unrelated reasons, I cannot use models for this form):
<div class="input-group" style="padding-top: 10px">
<div><input class="form-control" id="filename" value="Select a ZIP file to upload..." disabled></div>
<div class="input-group-btn"><input type="button" id="get_file" class="btn btn-primary" value="Browse"
style="margin-right: 3px;margin-left: 3px"></div>
<div class="input-group-btn"><input type="submit" id="upload"
class="btn btn-success" value="Upload" style="display: none"></div>
<input type="file" id="upload_file" name="upload_file" accept=".zip">
</div>
And then I some JavaScript as:
document.getElementById('get_file').onclick = function() {
document.getElementById('upload_file').click();
};
$('input[type=file]').change(function (e) {
document.getElementById('filename').value = ($(this).val());
document.getElementById('upload').style.display = "inline"
});
document.getElementById('upload').onclick = function() {
};
This works fine and I can upload the file just fine. However, now along with a file, I also want to send a string identifier. I am not sure how I can insert another request parameter on submit from this template?
The Django side looks like:
def upload(request):
"""
if request.method == 'POST' and request.FILES['upload_file']:
# Do things
So I need to add another parameter, so that I can do something like: request.GET.get('identifier') and this identifier key/value is inserted in the template code.
Does adding a hidden input inside the form work?
<input type="hidden" name="identifier" value="..."/>
On several pages of my web site (ASP.Net MVC, jQuery, KendoUI SPA), I have a modal window to upload a file.
addAttachment: function (e) {
$("form").on("submit", function (event) {
event.preventDefault();
});
e.preventDefault();
var formData = new FormData($("#formUpload")[0]);
var url = 'api/Attachments/UploadAttachment';
app.postFile(url, formData, function (statusCode) {
if (statusCode === 201) {
// File was created -- do stuff
}
});
},
<div id="addAttachmentWindow"
data-role="window"
data-height="300px"
data-width="600px"
data-modal="true"
data-title="Add Attachment"
data-visible="false">
<div class="row">
<form id="formUpload" class="form-horizontal">
<input type="hidden" id="hdnRecordId" name="recordId" data-bind="value: object.id" />
<div class="form-group">
<label class="col-sm-4 control-label" for="txtDocumentTitle">Title</label>
<div class="col-sm-6">
<input name="documentTitle" id="txtDocumentTitle" type="text" class="k-textbox" />
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label" for="fuFileInput">Document</label>
<div class="col-sm-6">
<input id="fuFileInput" name="files" type="file" />
</div>
</div>
<div class="col-sm-6 col-sm-offset-6">
<button data-role="button" data-icon="plus" data-bind="click: addAttachment">Add Attachment</button>
</div>
</form>
</div>
</div>
With the code for postFile
var postFile = function(uri, formData, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
callback(xhr.status);
}
};
xhr.open('POST', uri);
xhr.setRequestHeader("RequestVerificationToken", antiForgeryToken);
xhr.send(formData);
};
Most of the pages, this works fine, But on a couple of pages, it will issue the POST, without the form fields and immediately issue a GET for
/?recordId=1&documentTitle=documentTitleInput&files=FileNameHere.pdf
which goes to the Home Controller's Index function. If I go to one of the pages with this issue, do a Shift-Reload, and try the upload it will work as expected, the form fields are intact, and the callback is called.
Issues
Why the GET is being issued with the form fields in the query string immediately following the initial POST (even before the POST returns a response)
Why the form fields are empty, unless I do a shift-reload on some of pages, whilethe same code works fine on other pages.
I've tried creating an empty FormData, and appending the values to it, and played everything I can find to stop the normal submit event from happening (e.preventDefault(), e.stopPropogation(), return false etc.);
ok so some reading on the subject and its because the prevent default only works on elements, not on a form submit event, which is what your using...
create two submit inputs... one a button, the other a hidden input.. like so ..
<button type="button" id="submit">Submit</button>
<input style="display: none;" type="submit" id="realsubmit">
then do your jquery like so ...
$("#submit").on('click', function() {
//do stuff
$("#realsubmit").trigger('click');
});