Create PDF file with byte array and download/save it - javascript

I have an AJAX function who call a server side method, and this method call an API and it return a byte array. I want to convert this byte array in a PDF file, and then download the file. I have this code:
AJAX function:
function ObtenerF(nroF) {
debugger;
$.ajax({
type: 'POST',
url: '/De.aspx/BuscarFVW',
data: JSON.stringify({ nF: nroF }),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
debugger;
if (msg.d != null) {
window.open();
}
},
error: function () {
}
});
}
Code behind method:
[System.Web.Services.WebMethod]
public static byte[] BuscarFVW(string nF)
{
var respuesta = new Serv.L.SeL((U)HttpContext.Current.Session["UT"]).ObtenerF(nF);
if (respuesta != null)
{
File.WriteAllBytes(#"~\Content\tmp\hello.pdf", respuesta.F);
return respuesta.F;
}
else
return null;
}
I try this in the BuscarFVW method, but I can't pass a relative path as parameter in File.WriteAllBytes, and I don't know how to automatically download the new PDF file or save in the tmp folder in the project, and open a new tab with the PDF file (I can make this with an absolute path but this don't gonna work if I public the project in another server, but this work in my local with a path like C:/User/Desktop).
Any suggestion? Thank you.

You don't need to use ajax to download PDF and it's a bad habit to do so.
use can directly use a tag to download the file or iframe tag to present it.
And you can use window.location = '[your rout]';
to download the file.

Related

Error uploading single json file as input as workitem (DesignAutomation)

I could successfully compile design automation web application with input file, as RVT and Json attached.
But I need to pass only a Json file, as input for workItem. in ForgeDesignAutomation.js, I wrote it as below. But looks like inputfile need to be stringified . Please help me to correct the syntax below.
here 'inputFile' is a Json file, I am not uploading any rvt file, as my addin takes only a json file as input, which is array of strings and return a rfa file as output.
How to stringify 'inputFile', when it is just a .json file ?
function startWorkitem()
{
var inputFileField = document.getElementById('inputFile');
if (inputFileField.files.length === 0) { alert('Please select an input file'); return; }
if ($('#activity').val() === null) { alert('Please select an activity'); return };
var file = inputFileField.files[0];
let activityId = $('#activity').val();
if (activityId == null)
{
alert('Please select an activity'); return
};
if (activityId.toLowerCase() === "myfirst_da4ractivity+dev")
{
startConnection(function () {
var formData = new FormData();
formData.append('inputFile', file);
//file is not uploading-------I think I could not pass the Json file.
//I need to pass connection ID here too.
writeLog('Uploading input file...');
$.ajax({
url: 'api/forge/designautomation/workitems',
dataType: 'json',
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function (res)
{
writeLog('Workitem started: ' + res.workItemId);
}
});
});
}
}
From your question, you have a client, that submits to your server, which then submits to Forge.
That way, how you submit to api/forge/designautomation/workitems endpoint varies on how it's expecting the data. As you have a .json file, you don't need to stringfy is, it's passed as a file. If you decide to send it as data, then stringfy and adjust to data: { your JSON data here },
Assuming the file came from your client to your server, you can then submit that JSON file to Forge as an input for your Workitem.

How to add custom properties to file form javascript / jquery

I'm aiming to send fileform with images and additional information like height and width. I can't figure out how to add some custom props to file form object.
$("#saveImg").on('click', function () {
var formData = new FormData(),
allFiles = [];
$('input[name=fileUpload]').each(function (index) {
if (inputFileValidation(this)) {
(function (files) {
if (files.length != 0) { allFiles.push(files[0]); }
})(this.files)
}
});
for (var i = 0; i != allFiles.length; i++) {
var img = new Image()
img.src = window.URL.createObjectURL(allFiles[i]);
$(img).on('load', function () {
formData.append("files_h", img.naturalHeight);
formData.append("files_w", img.naturalWidth);
formData.append("files", allFiles[i]);
window.URL.revokeObjectURL(allFiles[i]);
});
}
$.ajax({
url: '#Url.Action("Upload", "Image")',
data: formData,
processData: false,
contentType: false,
type: "POST",
success: function () {}
errors: function () {}
});
});
[HttpPost]
public async Task<IActionResult> Upload (IList<IFormFile> files)
{
//do something ;
}
I also tried:
[HttpPost]
public async Task<IActionResult> Upload (IList<IFormFile> files, IList<IFormFile> files_h, IList<IFormFile> files_w)
{
//do something ;
}
Maybe you have another idea how to send image with additional data? I tried to convert file form and additional info to JSON by that didn't work.
Edit
Thank you all for your suggestion, they are really important to me because I will definitely use them in the future.
However, in this project I have already given up using the file reader due to its asynchrony and having fun with promise. The aim is simple and less javascript and more c#
I apologize for misleading you in the title javascript andjquery - and I mark the answer related to c #. I did this because this answer is related to my next task because the CoreCompat.System.Drawing library is undoubtedly still useful for editing photos in the future.
Thanks!!
If you want to get the Width and Height properties while uploading images in ASP.NET Core. I suggest you to install this package: CoreCompat.System.Drawing
Install-Package CoreCompat.System.Drawing -Version 1.0.0-beta006
In the server, after saving your files to the specific path. You could use System.Drawing.Image class to get the Width and Height properties:
using (var image = System.Drawing.Image.FromFile(filePath))
{
int width = image.Width;
int height = image.Height;
}
You don't have to add files_h and files_w properties to your client model before sending to server.
And then, by using this way, I've edited your js code to:
$("#saveImg").on('click', function () {
var formData = new FormData();
for (var input of Array.from($('input[name=fileUpload]')))
{
if (inputFileValidation(input) && input.files.length) {
formData.append('files', input.files[0]);
}
}
$.ajax({
url: '#Url.Action("Upload", "Image")',
data: formData,
processData: false,
contentType: false,
type: "POST",
success: function () {}
errors: function () {}
});
});
This is one approach; taken from there:
$('#btnUpload').click(function () {
// Checking whether FormData is available in browser
if (window.FormData !== undefined) {
var fileUpload = $("#FileUpload1").get(0);
var files = fileUpload.files;
// Create FormData object
var fileData = new FormData();
// Looping over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
// Adding one more key to FormData object
fileData.append('username', ‘Manas’);
$.ajax({
url: '/Home/UploadFiles',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
} else {
alert("FormData is not supported.");
}
});
Another approach is to use the FileReader class to read the uploaded file, convert it to a base 64 string. Then you can send the base 64 string to the server.

Is it possible to get a file in webmethod using path through Jquery .ajax() method?

As far as I know it is not possible to send a file to webmethod using Jquery/Ajax call. But what if I send the path of the file? And use that path to get the file in webmethod?
Client Side:
$.ajax({
type: "POST",
url: "Default.aspx/UploadFile",
data: JSON.stringify({ name: $('#fileData').val(); }),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function (data, status) {
console.log("CallWM");
alert(data.d);
},
failure: function (data) {
alert(data.d);
},
error: function (data) {
alert(data.d);
}
});
WebMethod:
[WebMethod]
public static string UploadFile(string name)
{
byte[] buffer;
FileStream fileStream = new FileStream(#"D:\Untitled.png", FileMode.Open, FileAccess.Read);
try
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
sum += count; // sum is a buffer offset for next reading
}
finally
{
fileStream.Close();
}
return "a";
}
Could this work? I think most modern browsers do not let you get real path of the file. Is there a workaround or something?
No, this could not work.
Hmm, you are talking about two different things. The file path you send will be resolved on the server. If you want to upload a file, you need to send it from the client. You mixed a lot up.
Imagine, you try to send this to the server: C:\Users\yourName\Test.txt,
where do you thing the server will try to find the file? The server will search on his local drive.
Try to use the default way to upload files. Maybe with some jQuery plugin and you make a request in the background. The internet will provide a lot of tutorials for your scenario. Just google a little bit around.
No, this won't work. if you want to upload file without post back for the entire page you could use iframe and set the target of your submitted form to this iframe
Not sure though but you can try by HttpPostedFileBase
foreach (string one in Request.Files)
{
HttpPostedFileBase file = Request.Files[one];
if ((file != null) && (file.ContentLength > 0) && !string.IsNullOrEmpty(file.FileName))
{
string fileName = file.FileName;
string fileContentType = file.ContentType;
byte[] fileBytes = new byte[file.ContentLength];
BinaryReader b = new BinaryReader(file.InputStream);
byte[] binData = b.ReadBytes(file.ContentLength);
}
}
I believe you can send a file to a webmethod just to simplify things use Base64
read your files to bytes convert your bytes to Base64 for example
var bytes = File.ReadAllBytes(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "filename.extension"));
then you can convert to Base64
var stringBase64=Convert.ToBase64String(bytes);
then in the other side convert the received base64 string to bytes
var bytes = Convert.FromBase64String(ReceivedString);
That is all

Json serialization: how to send c# data to javascript script. Error: Invalid character

I'm trying to send data from Entity Framework database to js script on my webpage. This is my MVC Controller:
public ActionResult Index()
{
var wordsToShow = db.Words.Where(w => w.OwnerName == User.Identity.Name); // && DateTime.Compare(w.NextReview, DateTime.Now) <= 0
ViewBag.wordsToShow = HttpUtility.HtmlDecode(new JavaScriptSerializer().Serialize(wordsToShow));
var test = ViewBag.wordsToShow;
return View();
}
And in index.cshtml I've put this code:
<script>
var wordsJson = "#ViewBag.wordsToShow.ToString()";
var wordsAsObject = JSON.parse(wordsJson);
</script>
The problem is, javascript says:
Invalid character
In the line where I'm parsing json to javascript object. The reason is: json string doesn't look like it should. This is part of what's inside "wordsJson" variable in web browser:
What can I do to make it work?
You're going about in an overly roundabout way. JSON is called "JavaScript Object Notation" for a reason. There's no need to put it in a string and re-parse it. You can just use the JSON as JavaScript.
ASP.NET MVC has a helper for serializing values as JSON, so you can just use that and assign it to a variable in your JavaScript:
<script>
var wordsAsObject = #Html.Raw(Json.Encode(ViewBag.wordsToShow));
</script>
This would eliminate the need to do the JSON serialization within your Action.
I suspect that the reason you're encountering this issue is that by default, values inserted into a view with # are automatically HTML encoded. You can use Html.Raw() to prevent this, as I've done above, but as I said, there's no reason to put it into a string first and parse it.
I always create Method that return JsonResult/string
like:
public string GetData()
{
//your logic here
string json_sales = JsonConvert.SerializeObject(<<your data>>);
return json_sales;
}
and in JavaScript I just do AJAX request:
$.ajax({
url: 'PUT_YOUR_URL_HERE_To_METHOD_GetData',
dataType: "json",
type: "GET",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ Make: maka.value }),
async: true, // Or false
cache: false,
success: function (data) {
//do something
}
},
error: function (xhr) {
alert('error');
}
})

I'm submitting the form through ajax using jquery serialization function

var values = $('#form_field').serialize();
dataS = "val="+values;
$.ajax({
type: "POST",
url: URL,
data: dataS,
cache: false,
dataType: 'json',
success: function(response)
{ },
});
But the form has an (<input type="file"> field) how do I pass the file into the form using this ajax serialization method. When I print $_FILES doesn't getting any output.
You can't past the $_FILES variable when using ajax. I can assure you that. Thanks.
Ajax does not support file uploads, you should use iframe instead.
you can check further detail here
Posting via Ajax file upload isn't straight forward. First, it isn't directly doable using XHR1.
There are two main ways to do the uploads, using a frame and using the XHR2 spec and the FormData object. This is the method I would recommend.
The easiest way to do this is then to perform two uploads. I'm going to borrow some code here, from GitHub user optikalefx to show you how to do it using jQuery:
// Ajax File upload with jQuery and XHR2
// Sean Clark http://square-bracket.com
// xhr2 file upload
// data is optional
$.fn.upload = function(remote,data,successFn,progressFn) {
// if we dont have post data, move it along
if(typeof data != "object") {
progressFn = successFn;
successFn = data;
}
return this.each(function() {
if($(this)[0].files[0]) {
var formData = new FormData();
formData.append($(this).attr("name"), $(this)[0].files[0]);
// if we have post data too
if(typeof data == "object") {
for(var i in data) {
formData.append(i,data[i]);
}
}
// do the ajax request
$.ajax({
url: remote,
type: 'POST',
xhr: function() {
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload && progressFn){
myXhr.upload.addEventListener('progress',function(prog) {
var value = ~~((prog.loaded / prog.total) * 100);
// if we passed a progress function
if(progressFn && typeof progressFn == "function") {
progressFn(prog,value);
// if we passed a progress element
} else if (progressFn) {
$(progressFn).val(value);
}
}, false);
}
return myXhr;
},
data: formData,
dataType: "json",
cache: false,
contentType: false,
processData: false,
complete : function(res) {
var json;
try {
json = JSON.parse(res.responseText);
} catch(e) {
json = res.responseText;
}
if(successFn) successFn(json);
}
});
}
});
};
I should also note that browser support for this is a little more limited, despite XHR2 being around for 2 years now: https://developer.mozilla.org/en-US/docs/Web/API/FormData contains more information as well as a Browser compatibility chart.

Categories

Resources