I know how the xtype: filefield works and I also realized that file upload does not use the regular ajax method to read and write data to database...
I can set up filefield normally and when I click the browse button I can select the necessary file.
this.fp = Ext.create('Ext.form.Panel', {
scope: this,
width: 200,
frame: true,
title: 'File Upload Form',
autoHeight: true,
bodyStyle: 'padding: 10px 10px 0 10px;',
items: [
{
xtype: 'filefield'
}
],
buttons: [
{ text: 'Upload',
handler: function () {
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
url: 'Upload.aspx',
waitMsg: 'Uploading your file...',
success: function (form, action) {
alert("OK:" + action.result.message);
},
failure: function (form, action) {
alert("Error:" + action.result.message);
}
});
}
}
}
]
});
What happens after the upload button is clicked is the problem... How would I get the file uploaded to server side...(sql db)... using c#
I tried creating an upload.aspx page with upload.aspx.cs and did this just to see if it worked...
public partial class Upload : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (context.Request.Files.Count > 0)
{
BinaryReader file = new BinaryReader(context.Request.Files[0].InputStream);
string line;
while ((line = file.ReadString()) != null)
{
// sql connection?
}
}
// prepare response
MessageOb result = new MessageOb();
result.success = true;
result.message = "Success";
}
}
But I get this error
Ext.Error: You're trying to decode an invalid JSON String:
Has someone documented where I can see the usual step to upload a file to sql db from extjs on client side and c# on serverside... or I'd really appreciate if someone can show me how it's done
The problem is probably related to how you return data from the upload form submit. Ext.JS requires the response to be JSON or XML, I would verify you are not returning a html document.
I presume MessageOb handles this somehow...maybe?
Uncaught Ext.Error: You're trying to decode an invalid JSON String: Form Submission using Ext JS and Spring MVC
Related
I'm a little lost on what should I do. I'm trying to upload a file along with its form data in one click, but I can't get the file. I tried to check the file in client and it's okay, but when receiving the file in the Controller, it's empty.
Problem
How do I upload the file along its formData using jQuery?
View
Assuming the other fields
<form id="_RegisterProduct" enctype="multipart/form-data">
<div>
<label>Product Description</label>
<textarea id="product_description" name="_product_description"></textarea>
<input type="file"
id="product_file"
name="product_file"
class="dropify" />
</div>
<button type="submit" id="snippet_new_save">Register Product</button>
</form>
<script>
$(function() {
rules: {
text: { required: true, minlength: 5 },
number: { required: true, minlength: 1 }
},
submitHandler: function (form) {
var fileUpload = $("#product_file").val();
var formData = $("#_RegisterForm").serialize();
var url = "#Url.Action("RegisterProduct", "Product")";
$.get(url, { fileUpload: fileUpload, formData }, function (e) {
if (e >= 1) {
console.log("success");
} else {
console.log("error");
}
});
}
})
</script>
Controller
public string RegisterProduct(HttpPostedFileBase fileUpload, AB_ProductModel formData)
{
var data = "";
using (var con = new SqlConnection(Conn.MyConn()))
{
var path = Server.MapPath("~/Content/uploads/products");
var Extension = "";
var fileName = "";
try
{
if(fileUpload.ContentLength > 0)
{
Extension = Path.GetExtension(fileUpload.FileName);
fileName = Path.GetFileName(fileUpload.FileName);
var com = new SqlCommand("dbo.sp_some_stored_procedure_for_saving_data",
con);
con.Open
data = Convert.ToString(com.ExecuteScalar());
var file_path = Path.Combine(path, data + Extension);
fileUpload.SaveAs(file_path);
}
}
catch (Exception ex)
{
data = ex.Message;
}
// data returns id if success or error message
}
return data;
}
Why serialize the form? This method creates a string that can be sent over to the server, but that is not what you want to do... In case of a file upload; see .serialize() function description here.
FormData type automatically manages the enctype for your forms (see here on MDN), so you can omit that—although you should consider using it, because it helps other members on the team understand the intent. If you want to use plain jQuery, you can simply attach the formData variable to the data field of the $.ajax call. See like here,
/*
* i know id-based selection should only have 1 element,
* otherwise HTML is invalid for containing multiple elements
* with the same id, but this is the exact code i used back then, so using it again.
**/
var formData = new FormData($('#form')[0]);
$.ajax({
type: 'POST',
processData: false,
contentType: false,
data: formData,
success: function (data) {
// The file was uploaded successfully...
$('.result').text('File was uploaded.');
},
error: function (data) {
// there was an error.
$('.result').text('Whoops! There was an error in the request.');
}
});
This of course requires that your HTML DOM contains these elements—I used the code I wrote for my article quite a few years back. Secondly, for my other part of the feature, I used Request.Files to capture the files that might have been uploaded with the request.
files = Request.Files.Count;
if(files > 0) {
// Files are sent!
for (int i = 0; i < files; i++) {
var file = Request.Files[i];
// Got the image...
string fileName = Path.GetFileName(file.FileName);
// Save the file...
file.SaveAs(Server.MapPath("~/" + fileName));
}
}
This way, I uploaded the files using jQuery and FormData.
You can check out the complete article I posted here, Uploading the files — HTML5 and jQuery Way!
Oh, and do not forget the suggestion made in the comment,
using (var com = new SqlCommand("dbo.sp_some_stored_procedure_for_saving_data", con))
{
con.Open(); // missed call?
data = Convert.ToString(com.ExecuteScalar());
// although, using should close here!
var file_path = Path.Combine(path, data + Extension);
fileUpload.SaveAs(file_path);
}
So, this was pretty much how you can do this.
Trying to find a resource that could point me in the right direction for downloading a file with this particular stack. It's more challenging than it seems, especially since I'm unable to use Razor in accordance with house rules.
The code execution can get from the markup, to the knockout, and then the C#, but it doesn't start a download like I would expect in ordinary webforms non-MVC ASP.NET.
mark up:
<div class="row">
<div class="col-2"><img data-bind="attr: {src: image}, click: $root.downloadFile/></div>
the knockout/javascript call:
self.downloadFile = function(e){
if(e) {
attachmentId = e.id;
helpers.ajax.getJson(root, "/Files/DownloadFile/", {fileId: attachmentId }, function(x){
attachmentId=0;
getFiles();
});
}
...
related javascript functions called here:
helpers.ajax.getJson = function(path, url, data, onSuccess, onError){
helpers.ajax.async('GET', path, url, {
data: data,
cache: false,
async: true,
error: onError,
success: onSuccess
});
};
function getFiles(){
self.files([]);
helpers.ajax.getJson(root, "/Files/GetFiles",
{ profileId: self.ProfileId() },
function (files) {
if(files) {
$.each(files, function (i, v) {
self.files().push(new file(v.AttachmentId, v.FileTypeDescr, v.FileExtension, v.FileName, v.UploadedBy, v.UploadDate, v.CompletionDate));
self.files.valuehasMutated();
});
}
});
}
C#
public FileResult DownloadFile(int fileId)
{
ODSAPI.AttachmentFile file = FileFunctions.GetById(fileId);
if(file != null)
{
return File(file.FileData, file.ContentType);
}
return null;
}
this returns the correct file information and the bits from the database when I step through the code and view the file variable.
you could use http://danml.com/download.html to download file from javascript AJAX return
for exmaple
download(data, 'Export.csv', 'application/csv');
where data will be return from your ajax request and file name and file type.
The JSON call in the Javascript was incorrect as it called for a JSON object. Rather, it should have been:
window.open(root + "/Files/DownloadFile?fileId=" + attId, '_blank');
instead of helpers.ajax.getJson()
I'm making an ajax call in the function as below
function UploadPic() {
debugger;
// generate the image data
var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL("image/png");
// Sending the image data to Server
$.ajax({
type: 'POST',
url: "baseimg.aspx",
data: { imgBase64: dataURL },
success: function () {
alert("Done, Picture Uploaded.");
window.opener.location.reload(true); // reloading Parent page
window.close();
window.opener.setVal(1);
return false;
}
});
}
And in the page load I'm trying to get the value as
protected void Page_Load(object sender, EventArgs e)
{
StreamReader reader = new StreamReader(Request.InputStream);
string Data = Server.UrlDecode(reader.ReadToEnd());
reader.Close();
}
In the dataURL I'm getting the value but in the page load 'string Data' is coming as empty.
I have referred to Capturing Image From Web Cam in ASP.Net to make this functionality.
The ajax is hitting successfully to the code then coming back and executing the success portion in the ajax call.
I'm finding no way out of it.
Since it is a POST operation, try checking the form variable like the following for the data string:
Request.Form["imgBase64"]
I know how to create a form that browses and selects a file, that's not my question. What I need is to get the content of the selected file, to send it to a server and proccess it. For now I only can get the file location.
I think it will be better if I get my file on client side (extjs), then send it to server, but I have no idea how to do this.
{
xtype: 'fileuploadfield',
hideLabel: true,
emptyText: 'Select a file to upload...',
id: 'upfile',
//name:'file',
width: 220
},
buttons:
[
{
text: 'Upload',
handler: function () {
obj.Import(Ext.getCmp('upfile').getValue())
}
}
]
Import(...) is my server function. I need to give it the file not only its path!!
Thank you in advance for your time
AFAIK Ext doesn't use HTML5 File API, so getting file content on JS side isn't straightforward. Probably simplest way to achieve that is to create custom handler. Eg:
{
xtype: 'fileuploadfield',
hideLabel: true,
emptyText: 'Select a file to upload...',
id: 'upfile',
//name:'file',
width: 220
},
buttons:
[
{
text: 'Upload',
handler: function () {
var file = Ext.getCmp('upfile').getEl().down('input[type=file]').dom.files[0]; // fibasic is fileuploadfield
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
obj.Import(e.target.result);
};
})(file);
reader.readAsBinaryString(file);
}
}
]
What you are doing Ext.getCmp('upfile').getValue() is clearly passing the file location to Import method. How do you expect the file content then? In order to upload a file, you need to submit a ExtJS form. You can do something like this:
handler: function() {
form.submit({
url: '/Gallery/Upload',
waitMsg: 'Uploading your file...',
success: function(form, action) {
alert('File form done!');
}
});
}
}
And on server side:
public void ProcessRequest(HttpContext context)
{
HttpPostedFile fileupload = context.Request.Files["file"];
// process your fileupload...
context.Response.ContentType = "text/plain";
context.Response.Write("Ok");
}
Update: You need to uncomment the name property of your fileuploadfield.
I am newish to events, and new to flash. I have managed to get files uploaded to my folder using Plupload. I am using a generic handler (New to that too!)
Here's my code:
<style type="text/css">
#import url(/plupload/js/jquery.plupload.queue/css/jquery.plupload.queue.css);
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
<script type="text/javascript" src="/plupload/js/plupload.full.js"></script>
<script type="text/javascript" src="/plupload/js/jquery.plupload.queue/jquery.plupload.queue.js"></script>
<script type="text/javascript">
$(function () {
$("#uploader").pluploadQueue({
// General settings
runtimes: 'gears,flash,silverlight,browserplus,html5',
url: '/uploader.ashx',
max_file_size: '10mb',
chunk_size: '1mb',
unique_names: true,
preinit: attachCallbacks,
// Resize images on clientside if we can
//resize: { width: 320, height: 240, quality: 90 },
// Specify what files to browse for
filters: [
{ title: "Image files", extensions: "jpg,gif,png" },
{ title: "Zip files", extensions: "zip" }
],
// Flash settings
flash_swf_url: '/plupload/js/plupload.flash.swf',
// Silverlight settings
silverlight_xap_url: '/plupload/js/plupload.silverlight.xap'
});
// Client side form validation
$('form').submit(function (e) {
var uploader = $('#uploader').pluploadQueue();
// Validate number of uploaded files
if (uploader.total.uploaded == 0) {
// Files in queue upload them first
if (uploader.files.length > 0) {
// When all files are uploaded submit form
uploader.bind('UploadProgress', function () {
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});
uploader.start();
} else
alert('You must at least upload one file.');
e.preventDefault();
}
function attachCallbacks(Uploader) {
Uploader.bind('FileUploaded', function(Up, File, Response) {
if ((Uploader.total.uploaded + 1) == Uploader.files.length) {
window.location = '/display.aspx';
}
});
}
});
And then in my code, my handler:
public class uploader : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
int chunk = context.Request["chunk"] != null ? int.Parse(context.Request["chunk"]) : 0;
string fileName = context.Request["name"] ?? string.Empty;
HttpPostedFile fileUpload = context.Request.Files[0];
var uploadPath = context.Server.MapPath(GlobalVariables.UploadPath);
using (
var fs = new FileStream(Path.Combine(uploadPath, fileName),
chunk == 0 ? FileMode.Create : FileMode.Append))
{
var buffer = new byte[fileUpload.InputStream.Length];
fileUpload.InputStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, buffer.Length);
}
context.Response.ContentType = "text/plain";
context.Response.Write("Success");
}
public bool IsReusable
{
get { return false; }
}
}
This is working 100%
Problem is, when it complete the upload, nothing happens. It displayed the fact that the files were uploaded.
I need to somehow tell a new method to fire. That is, I need to process the uploaded files. Move them to the right folder ... name them better ... add them to a database, and maybe redirect to the display screen.
So, I need the flash control to tell my code to do something (An event) and also, tell my code which files it can now process (The list of files uploaded).
Is this possible?
Edit: I added the attachCallbacks method, and it's attached. It now redirects to a page, but I need to it somehow send the list of files uploaded to a method (generic handler maybe?) and process the files. How do I redirect to a method?
........
uploader.bind('UploadProgress', function () {
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});
uploader.bind('UploadComplete', function (up, files) {
//files are uploaded, call script for each file...etc
});
uploader.start();
..........