External CSS when using SelectPDF - selectpdf

I have the following function that creates a PDF of a HTML page.
[Authorize]
public FileStreamResult PDFCV(int Id)
{
var user = _userManager.GetUserAsync(User);
HtmlToPdf converter = new HtmlToPdf();
var BaseUrl = HttpContext.Request.Host;
var Path = Url.Action("PreviewCv", "Cv", new { Id = Id });
try
{
converter.Options.HttpCookies.Add(".AspNetCore.Identity.Application", HttpContext.Request.Cookies[".AspNetCore.Identity.Application"]);
}
catch (Exception e)
{
Console.WriteLine(e);
}
string url = "";
try
{
url = BaseUrl + Path;
}
catch (Exception e)
{
Console.WriteLine(e);
}
try
{
PdfDocument doc = converter.ConvertUrl(url);
var PdfArray = doc.Save();
doc.Close();
return new FileStreamResult(new MemoryStream(PdfArray), "application/pdf");
}
catch (Exception e)
{
Console.WriteLine(e);
}
return new FileStreamResult(new MemoryStream(), "application/pdf");
}
This function allows me to get the PDF of the HTML page.
However it seems like it is not able to add the external CSS.
I have added it to the head of the HTML file.
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat"
</head>
When I access the page directly "/PDFPreview", I get the correct CSS.
Any suggestions on how I could force SelectPDF to use the correct CSS?

Try adding a delay before the conversion to allow the font files to download:
// specify the number of seconds the conversion is delayed
converter.Options.MinPageLoadTime = 2;

Related

Spring get request file not being downloaded

I want to download a file when clicking on a button in my AngularJS app which runs on Tomcat with a Java Spring backend but nothing is happening. The method in the backend is called and everything seems to have worked....but my browser doesn't download anything.
What am I missing?
Here's the AngularJS code, which logs Export-Response:[object Object]:
exportProjects() {
let filteredProjectIds = [];
for (let i in this.filteredProjects) {
for (let x = 0, l = this.filteredProjects[i].length; x < l; x++) {
if (!this.isOldProjectsBundle(this.filteredProjects[i][x])) {
filteredProjectIds.push(this.filteredProjects[i][x].id);
}
}
}
this.$http.get('/profiles/projectWordExport?filteredProjects=' + filteredProjectIds.join(",")).then(response => {
console.log("Export-Response:" + response);
return response;
});
}
This is the Java code being called (it's really being called, already debugged it, no errors occuring):
#RequestMapping(value = "/projectWordExport", method = RequestMethod.GET)
public void getProjectsWord(HttpServletRequest request, HttpServletResponse response, #RequestParam String filteredProjects) throws Exception {
//Load project objects from input string or load all projects if input empty
List<Project> projects = new java.util.ArrayList<>();
if (filteredProjects.isEmpty()) {
projects = projectRepository.findAll();
} else {
String[] pIds = filteredProjects.split(",");
for (String pId : pIds) {
projects.add(projectRepository.findById(Long.parseLong(pId)));
}
}
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-disposition", "attachment;filename=Projektexport.docx");
try {
SaveToZipFile saver = new SaveToZipFile(printer.printProjects(this.prepareProjectExport(projects)));
saver.save(response.getOutputStream());
response.flushBuffer();
} catch (NullPointerException e) {
response.setStatus(500);
response.sendError(500, "Fehler beim exportieren des Tests aufgetreten");
}
}
Put this in #RequestMapping annotation
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE

AngularJS via calling to Spring boot Controller responded with thymeleaf.exceptions.TemplateInputException

Hello i will tell you step by step,what i did,
1.I have HTML page named ManualChargesListV2.html,when page loads need to load the data in the Dropdown,so i use thymeleaf to show...
Here is #Controller Code
#GetMapping(value="/manualbillentry")
public ModelAndView doFetchUnitCharges(HttpSession session)
{
ModelAndView model = new ModelAndView();
WrpSession wrpsession = new WrpSession();
wrpsession = (WrpSession) session.getAttribute("totalObj");
try {
model.setViewName("ManualChargesListV2");
List<EntSetCharges> flatBillsManualList = new ArrayList<>();
flatBillsManualList = serbilldetails.doFetchUnitCharges(wrpsession);
model.addObject("manuallist",flatBillsManualList);
}
catch (Exception e){
e.printStackTrace();
}
return model;
}
2.The html page loads the data in dropdown perfectly,when choosing dropdown again need to hit the controller to show the data regarding selected dropdown value so i use to code like
<div class="form-group col-md-6">
<label for="chargelist">Select Charge *</label>
<select id="chargelist" class="form-control"
ng-model="selectedcharge"
ng-change="getChargeDetails(selectedcharge)">
<option> Select</option>
<option th:each="manualunitcharge:${manuallist}"
th:value="${manualunitcharge.pkSetCharges}"
th:text="${manualunitcharge.fkAssignCharges.chargeName}"></option>
</select>
</div>
it will call AngularJS ng-change="getChargeDetails(selectedcharge) method,it successfully hits the controller incl selected data.And Sends the data
#GetMapping(value = "manualbillentry/showmanuallist/{chargeid}")
private ResponseMsg doFetchManualChargesList(#PathVariable("chargeid")int chargeid,HttpSession session)
{
ResponseMsg response = new ResponseMsg();
WrpSession wrpsession = new WrpSession();
wrpsession = (WrpSession) session.getAttribute("totalObj");
try {
List<EntFlatIncome> unitChargesList = new ArrayList<>();
unitChargesList = serbilldetails.doFetchManualChargesList(chargeid,wrpsession);
response.setStatus("success");
response.setDataObj(unitChargesList);
}
catch (Exception e){
e.printStackTrace();
response.setStatus("failed");
}
return response;
}
var app = angular.module('ngapppmanual', []);
app.controller('ngctrlmanual', function($scope, $http, $location) {
$scope.ngshowchargelist = false;
$scope.getChargeDetails = function()
{
var url = $location.absUrl() + "/showmanuallist/" + $scope.selectedcharge;
var config = {
headers : {
'Content-Type' : 'application/json;charset=utf-8;'
}
}
$http.get(url, config).then(function(response)
{
if (response.data.status == "success")
{
$scope.manualresult = response.data.dataObj;
$scope.ngshowchargelist = true;
} else
{
$scope.getResultMessage = "Customer Data Error!";
}
},
function(response)
{
$scope.getResultMessage = "Fail!";
});
}
});
I need to Load the Data in in same HTML page But the issue is while responding result as incl Error code 500
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "manualbillentry/showmanuallist/1", template might not exist or might not be accessible by any of the configured Template Resolvers.
i cant understand the issue ,please someone helpme out...
you are using #Controller which returns html, instead you can use #RestController that returns JSON which angularJS is expecting

Create file on client side and send to server

i want to create a file in client side using Angular or Javascript and send it to server.
Using MVC controller my server function is
public void SavePivotFile(HttpPostedFileBase file)
{
try
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~"), System.Configuration.ConfigurationManager.AppSettings["reportsFolder"].ToString(), fileName);
file.SaveAs(path);
}
}
catch(Exception e)
{
throw;
}
}
Now, in my client side, i have a object that i want to send in SavePivotFile like a file. I tried this but doesnt work. The object 'options' is JSON.
$http({
method: 'GET',
url: '/FileManager/SavePivotFile',
params: {
file: options,
}
}).then(function successCallback(response) {
showNotification('The changes have been saved.', 'info');
}, function errorCallback(response) {
showNotification('Failed to save the file.', 'error');
});
Also i tried to create new FormData() before send but also doesn't work. How cat take options JSON object and pass it to server like file?
//C# Code
[HttpPost]
[Route('FileManager/SavePivotFile')]
// you can use [Allow(Role)] to allow particular role. Google it!
public void SavePivotFile(HttpPostedFileBase file)
{
try
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~"), System.Configuration.ConfigurationManager.AppSettings["reportsFolder"].ToString(), fileName);
file.SaveAs(path);
}
}
catch(Exception e)
{
throw;
}
}
//Angular Code
$http.post('FileManager/SavePivotFile',options)//Optionsistheobjectuwanttosend
.success(function(res){
//your code. since the c# method isvoid you will not get any response
})
.error(function(e){
//your error handling
})
The HttpPostedFileBase model should be similar to options. That way you can access the JSON in c#.
Let me know if this works.

Get an image of a vbhtml view as a byte array and save it to an oracle database

I need help on an mvc application in vb.net. In general terms I need to receive an image through the view and get it to work on the controller. I need to do this to convert the image to a byte array and save it to an oracle database. So my idea is to get the image and in the controller to convert it to a byte array or maybe there is some way to get the image already as a byte array and pass that array to the controller to save it to the database.
something like this its my View :
<div class="span11">
<div class="span4" id="depnac">
#Html.LabelFor(Function(m) m.DepNacPER)
#Html.DropDownListFor(Function(m) m.DepNacPER, Model.DepNacPER, New With {.class = "form-control"})
</div>
and this is my Model :
<Display(Name:="Region of birth")>
<Required(ErrorMessage:="you must select a option")>
Property DepNacPER As SelectList
I'm working on an ASP.NET Core app right now that uploads images. The image comes through to the controller via the request as a Stream. I'm then creating an Image object from that Stream but you could just read the data from it directly. That said, you might want to try to create an Image object to confirm that the data does represent a valid image.
Here's some relevant code from the view's script:
function uploadImage()
{
// This is a file upload control in a hidden div.
var image = $("#imageFile");
if (image[0].files.length > 0)
{
var formData = new FormData();
formData.append(image[0].files[0].name, image[0].files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "#Url.Content("~/events/uploadimage")");
xhr.send(formData);
xhr.onreadystatechange = function ()
{
if (xhr.readyState === 4 && xhr.status === 200)
{
var response = JSON.parse(xhr.responseText);
if (response.saveSuccessful)
{
// ...
} else
{
window.location.replace("#Url.Content("~/error")");
}
}
}
xhr.onerror = function(err, result)
{
alert("Error: " + err.responseText);
}
}
}
I'm in the process of replacing that code with some jQuery that does the heavy lifting but haven't got that far yet.
Here's some relevant code from the action:
[HttpPost]
public IActionResult UploadImage()
{
var requestForm = Request.Form;
StringValues tempImageFileNames;
string tempImageFileName = null;
string imageUrl = null;
var saveSuccessful = true;
var requestFiles = requestForm.Files;
if (requestFiles.Count > 0)
{
// A file has been uploaded.
var file = requestFiles[0];
using (var stream = file.OpenReadStream())
{
try
{
using (var originalImage = System.Drawing.Image.FromStream(stream))
{
// Do whatever you like with the Image here.
}
}
catch (Exception)
{
saveSuccessful = false;
}
}
}
if (saveSuccessful)
{
return Json(new {saveSuccessful, tempImageFileName, imageUrl});
}
else
{
return Json(new {saveSuccessful});
}
}
Sorry, it didn't occur to me at first that you're after VB code and this is C#. Hopefully you can still get the idea and I'll take the hit if someone dislikes the answer.

ResponseEnity with angular js

Controller code of Angular Js...
FactoryPBD.showPbdCostCompareData(data).success(
function(result) {
if(result != ""){
//doing my processing and working fine
}).error(function(result,status,message){
console.log("result" , result);
//getting undefined in all the above variable
});
Service code:
showPbdCostCompareData : function(filter) {
promise = $http({
url : 'pbd/showPbdCostCompareData?serachFilterJson='+JSON.stringify(filter),
method : "POST"
});
return promise;
}
Java Controller:-
#RequestMapping(value = "/showPbdCostCompareData", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<String> showPbdCostCompareData(HttpServletRequest request,
#RequestParam String serachFilterJson) {
try {
if (null != serachFilterJson && !"".equalsIgnoreCase(serachFilterJson)) {
Gson gson = new Gson();
SearchCriteriaBean searchCriteriaObj = gson.fromJson(serachFilterJson, SearchCriteriaBean.class);
CnHeaderBean cnHeaderBean = pbdServiceImpl.getPbdCostCompareCnHeaderData(searchCriteriaObj); //getting the value from sevice
List<PbdCostCompareBean> pbdCostCompareList = null;
if (null != cnHeaderBean) {
if("F".equalsIgnoreCase(cnHeaderBean.getPbdType())){
searchCriteriaObj.setFromPartIscb(cnHeaderBean.getFromPartIscb());
searchCriteriaObj.setToPartIscb(cnHeaderBean.getToPartIscb());
pbdCostCompareList = pbdServiceImpl.getPbdCostComparisonData(searchCriteriaObj); //getting the value from sevice
}else{
return new ResponseEntity<String>("Incorrect PBD Type",HttpStatus.SERVICE_UNAVAILABLE);
}
} else {
return new ResponseEntity<String>(HttpStatus.SERVICE_UNAVAILABLE);
}
HashMap<Integer, Object> costCompareMap = new HashMap<Integer, Object>();
costCompareMap.put(1, cnHeaderBean);
costCompareMap.put(2, pbdCostCompareList);
costCompareMap.put(3, pbdServiceImpl.validateUserAccess(searchCriteriaObj, serviceUtility.getUserFromSession(request)));
String pbdDataJsonResponse = gson.toJson(costCompareMap);
return new ResponseEntity<String>(pbdDataJsonResponse, HttpStatus.OK);
} else {
return new ResponseEntity<String>(HttpStatus.SERVICE_UNAVAILABLE);
}
} catch (C2PCException e) {
return new ResponseEntity<String>(e.getMessage(),HttpStatus.SERVICE_UNAVAILABLE);
}
}
I am using Spring Rest controller with Angular js for my project. Things are working fine and data is properly sent to client side when there is no error at Java side. But in case there is an exception at java side then depending upon the exception i want to return my message to the user.My response text is not getting transmitted to the client side. Any help will be appreciated. Code is provided above
Here in above e.getMessage, i get my custom message which i have set in mu service layer and throws the exception from there. But in the client side in error message i get all the values as undefined.
I assume that in angular js when an error occurs, a JSON is expected and not html/text
So, convert the exception to json.
You can create a class
ie
class ClassErrorMessage {
private String errorCode;
private String errorMessage;
ClassErrorMessage() {
}
//getters and setters
}
and then
catch (C2PCException e) {
ClassErrorMessage classErrorMessage= new ClassErrorMessage();
classErrorMessage.setErrorCode("some code that you may want");
classErrorMessage.setErrorMessage(e.getMessage());
String error = gson.toJson(classErrorMessage);
return new ResponseEntity<String>(error,HttpStatus.SERVICE_UNAVAILABLE);
}
and let me know if this worked for you

Resources