BLOB to PDF download using Java and angular 5 - java

I am trying to implement logic of download pdf from db on angular 5. I am facing issue in download file. File gets downloaded but throws error on opening -"Failed to load".
I have looked at so many blogs and question/answers but not able to find the mistake in my code.
In Database -> pdf file content saved as BLOB
Rest web service ->
In below code pdfData is the data from BLOB type column, which is byte[] in java code here
#GetMapping("downloadReport/{reportId}")
public StreamingResponseBody downloadDocument(byte[] pdfData) {
return outputStream -> {
//This way working for sample
/*try (InputStream inputStream = new ByteArrayInputStream(
Files.readAllBytes(Paths.get("D:/pdfWithoutPassword.pdf")))) {
IOUtils.copy(inputStream, outputStream);
}*/
//This way not working when data fetched from Database
try (InputStream inputStream = new ByteArrayInputStream(pdfData)) {
IOUtils.copy(inputStream, outputStream);
}
outputStream.close();
};
Angular 5 code
downloadReport(reportType: string, reportId: string) {
let fileDownloadUrl = environment.apiUrl + "/downloadReport" + "/" + reportId;
return this.httpClient
.get(fileDownloadUrl, { observe: 'response', responseType: "blob"})
.subscribe(response => this.saveFileToSystem(response.body)),
error => console.log("Error downloading the file."),
() => console.info("OK");
}
saveFileToSystem(input: any) {
const blob = new Blob([input], { type: 'application/octet-stream' });
saveAs(blob, "testingpdf1.pdf");
}
Looking for help in solving this. Thanks in advance!

Here another way I did it you you can change :
#RequestMapping(value = "/generateReport", method = RequestMethod.POST)
public ResponseEntity<byte[]> generateReport(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
StringBuilder filename = new StringBuilder("MyPdfName").append(".pdf");
byte[] bytes = pdfGeneratorService.generatePDF();
headers.add("content-disposition", "inline;filename=" + filename.toString());
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
return response;
}

Try this :
From your html page
YourPdf.pdf
From your js file
generatePdf() {
this.yourService.generatePdf()
.subscribe(pdf => {
let mediaType = 'application/pdf';
let blob = new
Blob([this.converterService.base64ToArrayBuffer(pdf.pdfByteArray)], { type: mediaType });
saveAs(blob, fileName);
}, err => {
console.log('Pdf generated err: ', JSON.stringify(err));
});
}
Your converter service:
import { Injectable } from "#angular/core";
#Injectable()
export class ConverterService {
base64ToArrayBuffer(base64) {
var binaryString = window.atob(base64);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
}

Related

Current request is not of type MultipartHttpServletRequest

I'm trying to send an image + object from Angular to Spring Boot but everytime I try I get this error:
Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]
This is my Angular code:
addPostWithIMG(image: File, postRequest: PostRequest): Subscription {
const headers = new HttpHeaders();
headers.append('Content-Type', ' multipart/form-data content');
var file: FormData = new FormData();
file.append('file', image);
file.append('postRequest', JSON.stringify(postRequest));
console.log(file)
return this.http.post<PostRequest>(`${this.baseUrl + "multi"}`, file, {headers: headers}).subscribe({
next: (data: any) => {
console.log(data)
},
error: (err: any) => {
console.error(err)
},
complete: () => {
console.log("Done")
}
});
}
This my Spring Boot side:
#PostMapping(path = "multi")
public String multi(MultipartHttpServletRequest request) throws IOException {
String postJSON = request.getParameter("postRequest");
PostRequest = new Gson().fromJson(post, PostRequest.class);
MultipartFile file = request.getFile("file");
Binary files = new Binary(file.getBytes());
File fileToSave = new File("Post/src/main/resources/" + postRequest.getPostId() + ".png");
log.info("file: {}", fileToSave.getAbsolutePath());
if (!fileToSave.exists()) {
log.info("file created: {}", fileToSave);
fileToSave.createNewFile();
} else {
log.info("file already exist: {}", fileToSave);
}
// Try-with-resource
try (OutputStream out = new FileOutputStream(fileToSave.getAbsolutePath())) {
out.write(files.getData());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
return "Image saved";
}
Can Anyone help me to find the reason of thi exception
Thank you very much
Try to don't add:
headers.append('Content-Type', ' multipart/form-data content');
The web will automatically set for you

Converting Java code to C# httpClient POST custom request to a conversion server

I have an example working solution in Java but I need a solution in C# that can be called from a legacy database system.
So basically create a request with custom headers, load a Word document, and send the request. The server will then convert the Word document and return the PDF which then needs to be saved to disk.
Can someone please assist.
Java Code
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class NewMain {
public static void main(String[] args) throws IOException {
String source = args[0];
String target = args[1];
URL url = new URL("http://localhost:9998");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/vnd.com.documents4j.any-msword");
conn.setRequestProperty("Accept", "application/pdf");
conn.setRequestProperty("Converter-Job-Priority", "1000");
// File wordFile = new File("C:/temp2/Sample.doc");
File wordFile = new File(source);
InputStream targetStream = new FileInputStream(wordFile);
OutputStream os = conn.getOutputStream();
long length = targetStream.transferTo(os);
os.flush();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
InputStream in = conn.getInputStream();
// OutputStream out = new FileOutputStream("C:/temp2/Sample-BBB-doc.pdf");
OutputStream out = new FileOutputStream(target);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
in.close();
out.close();
os.close();
conn.disconnect();
}
}
The following is C# code that I have been progressing with [Note not attempt to save the returned PDF as yet] - below this is the server response:
using System;
using System.Net;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http.Headers;
namespace HttpPOST10
{
class Program
{
public static string MyUri { get; private set; }
static void Main(string[] args)
{
string url = "http://localhost:9998";
Uri myUri = new Uri(url);
string filePath = #"C:\temp2";
string srcFilename = #"C:\temp2\Sample.doc";
string destFileName = #"C:\temp3\Sample.pdf";
UploadFile(url, filePath, srcFilename, destFileName);
}
private static bool UploadFile(string url, string filePath, string srcFilename, string destFileName)
{
HttpClient httpClient = new HttpClient();
using var fileStream = new FileStream(srcFilename, FileMode.Open);
var fileInfo = new FileInfo(srcFilename);
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Headers = {
{ HttpRequestHeader.ContentType.ToString(), "application/vnd.com.documents4j.any-msword" },
{ HttpRequestHeader.Accept.ToString(), "application/pdf" },
{"Converter-Job-Priority", "1000"}
},
Content = new StreamContent(fileStream)
};
Console.Write("httpRequestMessage:" + httpRequestMessage);
var response = httpClient.SendAsync(httpRequestMessage).Result;
Console.Write("response:" + response);
return true;
}
}
}
Http Response:
httpRequestMessage:Method: POST, RequestUri: 'http://localhost:9998/', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
ContentType: application/vnd.com.documents4j.any-msword
Accept: application/pdf
Converter-Job-Priority: 1000
}response:StatusCode: 500, ReasonPhrase: 'Request failed.', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: close
Content-Length: 1031
Content-Type: text/html; charset=ISO-8859-1
Alternative Solution restSharp
I have made some progress today and managed to create a basic working solution in restSharp. This was derived from investigating how things work in Postman and starting with the generated code snippet. The challenge was getting the source document recognized so it could be uploaded (seems like a bit of confusion as to what each of the file parameters are used for):
using System;
using System.IO;
using System.Net;
using RestSharp;
using RestSharp.Extensions;
namespace HttpPOST12RestSharp
{
class Program
{
static void Main(string[] args)
{
var source = "C:\\temp2\\Sample.doc";
var target = #"C:\temp3\Sample-HttpPOST12RestSharp.pdf";
var client = new RestClient("http://localhost:9998");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/vnd.com.documents4j.any-msword");
request.AddHeader("Accept", "application/pdf");
request.AddHeader("Converter-Job-Priority", " 1000");
request.AddParameter("application/vnd.com.documents4j.any-msword", File.ReadAllBytes(source), Path.GetFileName(source), ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine("response.StatusCode: " + response.StatusCode);
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception($"Unable to download file");
}
else
{
response.RawBytes.SaveAs(target);
Console.WriteLine("Target Document: " + target);
}
}
}
}
Alternative Solution HttpClient / HttpRequestMessage
This solution uses HttpClient / HttpRequestMessage with no external libraries and saves the returned PDF response to disk.
using System;
using System.Net;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
namespace HttpPOST10
{
class Program
{
public static string MyUri { get; private set; }
static void Main(string[] args)
{
string url = "http://localhost:9998";
// string url = "http://localhost:8888"; // Fiddler
Uri myUri = new Uri(url);
string srcFilename = #"C:\temp2\Sample.doc";
string destFileName = #"C:\temp3\Sample-HttpPOST10.pdf";
UploadFileAsync(url, srcFilename, destFileName);
}
private static async System.Threading.Tasks.Task<bool> UploadFileAsync(string url, string srcFilename, string destFileName)
{
HttpClient httpClient = new HttpClient();
byte[] data;
data = File.ReadAllBytes(srcFilename);
HttpContent content = new ByteArrayContent(data);
content.Headers.Add("Content-Type", "application/vnd.com.documents4j.any-msword");
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Headers = {
// { HttpRequestHeader.ContentType.ToString(), "application/vnd.com.documents4j.any-msword" },
{ HttpRequestHeader.Accept.ToString(), "application/pdf" },
{ "Converter-Job-Priority", "1000" },
},
Content = content
};
Console.Write("httpRequestMessage:" + httpRequestMessage);
var response = httpClient.SendAsync(httpRequestMessage).Result;
Console.Write("response:" + response);
using (var fs = new FileStream(destFileName, FileMode.CreateNew))
{
await response.Content.CopyToAsync(fs);
}
return true;
}
}
}
Request / Response
httpRequestMessage:Method: POST, RequestUri: 'http://localhost:9998/',
Version: 1.1, Content: System.Net.Http.ByteArrayContent, Headers: {
Accept: application/pdf Converter-Job-Priority: 1000 Content-Type:
application/vnd.com.documents4j.any-msword }response:StatusCode: 200,
ReasonPhrase: 'OK', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: { Vary: Accept-Encoding
Transfer-Encoding: chunked Date: Mon, 12 Apr 2021 06:49:45 GMT
Content-Type: application/pdf

Return pdf from controller and display on front end in spring

I have pdf saved in blob format in my database. It's coming empty on front end.
Here is my controller call:
#RequestMapping(value = "/viewDocument", method = RequestMethod.GET, produces=MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> viewDocument()
{
HttpHeaders headers = new HttpHeaders();
ByteArrayInputStream bis = null;
try{
File uFile = null;
uFile = maintainFileService.getDocument(123456L);
bis = new ByteArrayInputStream(uFile.getFile());
headers.add("Content-Disposition", "inline; filename=pdf.pdf");
}
catch(Exception e){
logger.error("Exception while viewing the pdf.");
}
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_PDF)
.body(new InputStreamResource(bis));
}
And here is my ajax call:
$.ajax({
type : "GET",
url: "/esubmission/recorder/search/viewDocument" ,
timeout : 100000,
success : function(result) {
window.open(result);
},
error : function(e) {
console.log("ERROR: ", e);
},
done : function(e) {
console.log("DONE");
}
});
I think I am missing something but just couldn't figure it out. TIA

Files not getting Downloaded in Spring

There is a page where i have files list. On cliking on any of the .txt it must get downloaded and a notification should be displayed as the notification we get in download anything on GoogleChrome.
This is my Js which is called after cliking on .txt files
Here i am doing is, i am getting the filename and the filepath of the selected file. And then using ajax sending those filename and filepath to the spring servlet.
if (options.downloadable) {
$(easyTree).find('.easy-tree-toolbar').append('<div class="fileDownload"><button class="btn btn-default btn-sm btn-primary"><span class="glyphicon glyphicon-circle-arrow-down"></span></button></div>');
$(easyTree).find('.easy-tree-toolbar .fileDownload > button').attr('title', options.i18n.downloadTip).click(function() {
var selected = getSelectedItems();
var fileName = $(selected).find(' > span > a').text();
alert("fileName**" + fileName);
var hrefValue = $(selected).find(' > span > a').attr('href');
alert("hrefValue**" + hrefValue);
if (selected.length <= 0) {
$(easyTree).prepend(warningAlert);
$(easyTree).find('.alert .alert-content').html(options.i18n.downloadNull);
} else {
$.ajax({
url: "/ComplianceApplication/downloadFileFromDirectory",
type: "GET",
data: {
hrefValue: hrefValue,
fileName: fileName
},
success: function(data) {
//$(selected).remove();
//window.location.reload();
},
error: function(e) {
}
});
}
});
}
This is my springController. Here I am getting all the data properly but the problem is file is not getting downloaded and am not even getting any error so that I can come to know what mistake I am doing.
#RequestMapping(value="/downloadFileFromDirectory",method = RequestMethod.GET)
public #ResponseBody void downloadFileFromDirectory(#PathVariable("fileName") String fileName,#RequestParam(value = "hrefValue") String hrefValue,HttpServletRequest request, HttpServletResponse response,Model model){
System.out.println("hrefValue***"+hrefValue);
String filePath = hrefValue;
ServletContext context = request.getSession().getServletContext();
File downloadFile = new File(filePath);
FileInputStream inputStream = null;
OutputStream outStream = null;
try {
inputStream = new FileInputStream(downloadFile);
response.setContentLength((int) downloadFile.length());
response.setContentType(context.getMimeType(downloadFile.getName()));
// response header
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
//String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
response.setHeader(headerKey, headerValue);
// Write response
outStream = response.getOutputStream();
IOUtils.copy(inputStream, outStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != inputStream)
inputStream.close();
if (null != outStream)
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Any suggestions ???
I usually use this kind of code with no problem:
public ResponseEntity<InputStreamResource> downloadFile(#PathVariable("idForm") String idForm)
{
try
{
File parent = new File(csvFilesPath);
File file = new File(parent, idForm+".csv");
HttpHeaders respHeaders = new HttpHeaders();
MediaType mediaType = new MediaType("text","csv");
respHeaders.setContentType(mediaType);
respHeaders.setContentLength(file.length());
respHeaders.setContentDispositionFormData("attachment", "file.csv");
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}
catch (Exception e)
{
String message = "Errore nel download del file "+idForm+".csv; "+e.getMessage();
logger.error(message, e);
return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
The problem it's in you ajax code, so you can use JQuery File Download.
It's as simple as
$.fileDownload('/url/to/download.pdf');
Here you can see a tutorial
http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/

Ajax call to download pdf file in jsp

I've tried to open itext created pdf file using jsp code but not opening valid pdf file.
BTW if I'll open pdf in generated path then it is valid generated pdf.
<%
//code to generate pdf on file location.
String pdfurl = filePDF.getAbsolutePath();
File pdf = null;
try {
System.out.println("pdfurl : " + pdfurl);
response.setCharacterEncoding("utf-8");
pdf = new File(pdfurl);
response.setContentType("application/pdf");
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-Disposition", "inline;filename=checklist.pdf");
response.setHeader("Accept-Ranges", "bytes");
response.setContentLength((int) pdf.length());
OutputStream sos = response.getOutputStream();
FileInputStream input = new FileInputStream(pdf);
BufferedInputStream buf = new BufferedInputStream(input);
int readBytes = 0;
while ((readBytes = buf.read()) != -1) {
sos.write(readBytes);
}
System.out.println("Finished writing bytes to output stream.");
sos.flush();
sos.close();
input.close();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (null != pdf && pdf.exists() && !pdf.isDirectory()) {
try {
pdf.delete();
System.out.println("Deleted file from " + pdfurl + " successfully");
} catch (Exception ex) {
System.out.println("Error while deleting pdf from : " + pdfurl);
}
}
}
%>
And angularJS code for ajax call:
pfqa.createDocument = function(action,data){
$("body").addClass("loading");
var deferred = $q.defer();
var paramJsonObj= {
'userId' : userId,
};
var data = angular.copy(paramJsonObj);
data = angular.toJson(data);
$http({
url : 'services/downloadPDF.jsp',
dataType: 'json',
method : 'POST',
headers : {
'Content-type' : 'application/json',
},
data: {data: paramJsonObj},
responseType : 'arraybuffer'
}).success(function(data, status, headers, config) {
var file = new Blob([ data ], {
type : 'application/json'
});
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = 'checklist.pdf';
document.body.appendChild(a);
a.click();
}).error(function(data, status, headers, config) {
});
$("body").removeClass("loading");
}
Please guide me what I'm missing here.
What you are missing here is :
Use : application/pdf instead of application/json
$http({
url : 'services/downloadPDF.jsp',
dataType: 'json',
method : 'POST',
headers : {
'Content-type' : 'application/pdf',
},
data: {data: paramJsonObj},
responseType : 'arraybuffer'
}).success(function(data, status, headers, config) {
var file = new Blob([ data ], {
type : 'application/pdf'
});
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = 'checklist.pdf';
document.body.appendChild(a);
a.click();
}).error(function(err) {
console.log(err);
});
That's it !!!

Categories

Resources