Generating document preview using client side script - javascript

I am working on a solution where i need to generate preview in popup for (pdf,word,excel) .I have achieved same by converting all format using Aspose.Words and Aspose.Cells. Below is my code:
public ActionResult PreviewDoc(string fileName)
{
string fileExtension = fileName.Substring(fileName.LastIndexOf(".") + 1);
string pathSource = Server.MapPath("~/"+ fileName);
MemoryStream streamToWrite = new MemoryStream();
using (FileStream file = new FileStream(pathSource, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
streamToWrite.Write(bytes, 0, (int)file.Length);
}
var previewStream = this.GetPdfStream(fileExtension, streamToWrite);
// Load the document.
// Convert the document to byte form.
byte[] docBytes = previewStream.ToArray();
// The bytes are now ready to be stored/transmitted.
// Now reverse the steps to load the bytes back into a document object.
MemoryStream inStream = new MemoryStream();
inStream.Write(docBytes, 0, docBytes.Length);
inStream.Position = 0;
return new FileStreamResult(inStream, "application/pdf");
}
public MemoryStream GetPdfStream(string extension, MemoryStream streamToRead)
{
MemoryStream outStream = new MemoryStream();
if (extension.Trim().ToLower() == "doc" || extension.Trim().ToLower() == "docx")
{
Aspose.Words.Document doc = new Aspose.Words.Document(streamToRead);
// Save the document to stream.
doc.Save(outStream, SaveFormat.Pdf);
}
else if (extension.Trim().ToLower() == "xls" || extension.Trim().ToLower() == "xlsx")
{
Aspose.Cells.Workbook workbook = new Aspose.Cells.Workbook(streamToRead);
workbook.Save(outStream, Aspose.Cells.SaveFormat.Pdf);
}
else
{
outStream = streamToRead;
}
return outStream;
}
But as Aspose requires licesnse which i don't have so do we have any client side approach where we return stream from mvc controller and convert that to preview at client side and open in new window?

Yes it is true that a valid license is a must to achieve the task. You can convert and send the output stream to client browser but it will contain the Aspose watermark. Furthermore you can get a temporary license for evaluation. Please visit the link and get the temporary license for 30 days.
I work with Aspose as Developer evangelist.

Related

Java spring downloading a file from a blob: URL to the machine

I am trying change the loader of a website, the user change it by completing a form in react, i send the blol:url to my back which is java spring and I can't manage to put it as a file to put it one the server :D
I tried multiples methods :
ClassPathResource classPathResource = new ClassPathResource("");
String path2 =(classPathResource.getFile().getAbsolutePath());
path2 =path2.replace("back\\target\\classes", "front\\src\\img\\loader.gif");
File file = new File(path2);
Blob blob = new SerialBlob(path.getBytes());
InputStream inputStream = blob.getBinaryStream();
OutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
ClassPathResource classPathResource = new ClassPathResource("");
String path2 =(classPathResource.getFile().getAbsolutePath());
path2 =path2.replace("back\\target\\classes", "front\\src\\img\\loader.gif");
File file = new File(path2);
URL url = new URL(path);
InputStream inputStream = url.openStream();
FileOutputStream fileOutputStream = new FileOutputStream(file);
FileCopyUtils.copy(inputStream, fileOutputStream);
In all case i can replace the actual loader.gif but it just result a broken file which doesnt even charge

sending string from C# to client and converting into Uint8Array type byte array and then into blob to open excel file. Corgi Involved

So here in C# code i am sending corgi to client which has corgiBabies. Using ClosedXml here.
var wbCorgiBabiesTemplate = new XLWorkbook();
var wsCoriBabiesAmendementTemplate = wbCorgiBabiesTemplate.Worksheets.Add(" Work Sheet Corgi baby Template");
wsCoriBabiesAmendementTemplate.Cell("A1").Value = "Corgi Parent";
wsCoriBabiesAmendementTemplate.Cell("B1").Value = "Corgi Child";
wsCoriBabiesAmendementTemplate.Cell("A2").Value = "Petunia";
wsCoriBabiesAmendementTemplate.Cell("B2").Value = "Khaleesi";
using (var ms = new MemoryStream())
{
wbCorgiBabiesTemplate.SaveAs(ms);
byte[] Corgibabies = ms.ToArray();
}
corgi.Corgibabies = System.Text.Encoding.UTF8.GetString(Corgibabies);
return corgi;
After that in Client i want to open corgibabies in excel sheet but the conversion here is wrong somewhere i think that excel sheet doesn't open correctly.
var fileName = 'CorgiBabies.xlsx';
dataAccessService.get('corgi')
.then(function(response) {
let utf8Encode = new TextEncoder();
var strBytes = utf8Encode.encode(response.corgiBabies);
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var file = new Blob([strBytes], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
var fileURL = window.URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
})
Below what excel sheet gives me error in image
Assuming you're on .Net Core+ (otherwise you can find the System.Buffers Nuget package for .Net standard or framework), on server side try
using System.Buffers;
using System.Buffers.Text;
and insert
var outputBuffer = new Span<byte>();
var status = Base64.EncodeToUtf8(Corgibabies, outputBuffer, out var consumed, out var written);
// sanity check
// if (status != OperationStatus.Done) throw new Exception();`
// do the above just before replacing
// System.Text.Encoding.UTF8.GetString(Corgibabies);
// with
System.Text.Encoding.UTF8.GetString(outputBuffer);
Now I'm pretty certain that will ensure that the server responds with what the client should expect but I'm not set up to test the Javascript side of things (yet). In the meantime let me know if this helps you make progress.
PS1: the error in your original code was the implicit assumption that Corgibabies is an array containing the bytes of a UTF8 encoded string. It actually contains the raw bytes of what would normally be an .xlsx file on disk. What is needed is to make that into text (Base64 encoding) and ensure that text is UTF8. Obviously in the Javascript you need to do the reverse - UTF8 Base64 to binary, save to disk, open in Excel...
Instead of returning string as the Content, you can make it work with File.
public ActionResult Get()
{
var wbCorgiBabiesTemplate = new XLWorkbook();
var wsCoriBabiesAmendementTemplate = wbCorgiBabiesTemplate.Worksheets.Add(" Work Sheet Corgi baby Template");
wsCoriBabiesAmendementTemplate.Cell("A1").Value = "Corgi Parent";
wsCoriBabiesAmendementTemplate.Cell("B1").Value = "Corgi Child";
wsCoriBabiesAmendementTemplate.Cell("A2").Value = "Petunia";
wsCoriBabiesAmendementTemplate.Cell("B2").Value = "Khaleesi";
wbCorgiBabiesTemplate.SaveAs("new.xlsx");
var ms = new MemoryStream();
wbCorgiBabiesTemplate.SaveAs(ms);
ms.Position = 0;
var fileName = "CorgiBabies.xlsx";
return File(ms, "application/octet-stream", fileName);
}
Api call:
or
fetch('https://localhost:7135/api/downloadExcel')
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// the filename you want
a.download = 'CorgiBabies.xlsx';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.catch(() => alert('oh no!'));
Ref: git
ClosedXML has several extensions that will help you acheive what you need :
ClosedXML.Extensions.AspNet
ClosedXML.Extensions.Mvc
ClosedXML.Extensions.WebApi
You can install the appropriate extension for your project, to help give you a fast access to download the workbook. You can also save the file on disk, and pass the file link (path) to JavaScript, and continue your work on the file from JavaScript.
if you need to know how you would let the user download the file from ASP.NET,
then you can do this :
Simple workbook :
C#: ASP.NET MVC
[HttpGet]
public ActionResult Download(string fileName)
{
// create workbook
var workbook = new XLWorkbook();
var sheet = workbook.Worksheets.Add("Worksheet 1");
sheet.Cell("A1").Value = "A1";
sheet.Cell("B1").Value = "B1";
sheet.Cell("A2").Value = "A2";
sheet.Cell("B2").Value = "B2";
// get workbook bytes
byte[] workbookBytes;
using (var memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
workbookBytes = memoryStream.ToArray();
}
return File(workbookBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
C#: ASP.NET Web Forms
public void Export(HttpResponse response, string fileName)
{
// create workbook
var workbook = new XLWorkbook();
var sheet = workbook.Worksheets.Add("Worksheet 1");
sheet.Cell("A1").Value = "A1";
sheet.Cell("B1").Value = "B1";
sheet.Cell("A2").Value = "A2";
sheet.Cell("B2").Value = "B2";
HttpResponse httpResponse = response;
httpResponse.Clear();
httpResponse.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
httpResponse.AddHeader("content-disposition", $"attachment;filename=\"{fileName}.xlsx\"");
using (var memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
memoryStream.WriteTo(httpResponse.OutputStream);
}
httpResponse.End();
}
the above examples will directly download the file into the client device. However, if you want to pass the workbook bytes to the JavaScript, you will need to convert it to base64 string and pass it to the JavaScript like so :
var base64String = Convert.ToBase64String(workbookBytes);
Then from JavaScript decode it to Uint8Array :
/*
JavaScript
*/
// get base64 string array and decoded it
var data = atob(serverSideResult);
var array = new Array(data.length);
for (var i = 0; i < data.length; i++) {
array[i] = data.charCodeAt(i);
}
// final result
var dataUint8Array = new Uint8Array(array);
now you can work with dataUint8Array as normal Uint8Array.
if you want to pass it back to the server-side, you can convert the array to base64 string, and pass it to the server-side like so :
/*
JavaScript
*/
let binaryString = ''
for (var i = 0; i < dataUint8Array.byteLength; i++) {
binaryString += String.fromCharCode(dataUint8Array[i]);
}
//pass base64Result to the server-side (C#)
var base64Result = window.btoa(binaryString);
then from C# you just need to convert it back to array from base64 string like so :
var bytes = Convert.FromBase64String(dataReceivedFromJavaScript);
where bytes would be byte[].

image/png response from restapi not displaying in browser

I am getting corrupted image icon while displaying b64 encoded png image response from rest API.
javascript-
function getcap(){
var http = new XMLHttpRequest()
http.open("GET", "http://localhost:8888/newcaptcha",true)
http.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
http.setRequestHeader("Access-Control-Allow-Origin", "http://localhost:8888");
http.send()
http.onload = () => {
var resp=unescape(encodeURIComponent(http.responseText));
var b64Response = window.btoa(resp);
console.log('data:image/png;base64,'+b64Response);
document.getElementById("capimg").src = 'data:image/png;base64,'+b64Response;
}
}
html -
<div id="newCaptcha" onClick="getcap()" ><h5>new captcha:</h5><img id="capimg" width="30" height ="30"/></div>
b64 encoded response-
server code -
#CrossOrigin(origins = "http://localhost:8080")
#RequestMapping(value = "/newcaptcha", method = RequestMethod.GET, produces = "image/png")
public #ResponseBody byte[] getnewCaptcha() {
try {
Random random = new Random();
imgkey= random.nextInt(3);
InputStream is = this.getClass().getResourceAsStream("/"+captcheMap.get(imgkey)+".png");
BufferedImage img = ImageIO.read(is);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageIO.write(img, "png", bao);
return bao.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
The base 64 response attached doesn't seem to actually load the image, if I open it in browser.
Secondly, I can see that that one problem that can cause this is reloading of DOM element img, if its not handled by any framework, you may have to manually intervene. To check this, you can test using a local image and load that. If it doesn't work, then you got your root cause. And if it does, then this base64 response is an issue.
Also, check the console for any errors and do update here.
As I pointed out in comments, probably you don't need b64. However, if you really want, read this.
There are tons on questions on Stackoverflow on this subject, and few answers. I have put together all pieces.
The point is that btoa() badly supports binary data.
Here: convert binary data to base-64 javaScript you find the suggestion to use arraybuffers as responseType, instead of just text.
Here: ArrayBuffer to base64 encoded string you find a function that converts arraybuffers to b64.
Putting all togheter:
function getcap(){
var http = new XMLHttpRequest();
http.open("GET", "/newcaptcha",true);
http.responseType = 'arraybuffer';
http.send();
http.onload = () => {
console.log(http.response);
var b64Response = _arrayBufferToBase64(http.response);
document.getElementById("capimg").src = 'data:image/png;base64,'+b64Response;
}
}
function _arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}

Saving jpg file with cloud-code Parse-Server

I'm trying to save jpg files with cloud code on parse server ...
On Android I can do it using this way
Bitmap bitmap = ((BitmapDrawable) myImageView.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte [] byteArrayPhotoUpdate = stream.toByteArray();
final ParseFile pictureFileParse = new ParseFile( newUserInfo.getObjectId() + ".JPEG",byteArrayPhotoUpdate);
newUserInfo.put("profile_picture",pictureFileParse);
newUserInfo.saveInBackground();
But I have no idea how to do this in the cloud code. I call my cloud code functions like this
HashMap<String, String> params = new HashMap();
ParseCloud.callFunctionInBackground("myCloudFuncion", params, new FunctionCallback<String>() {
#Override
public void done(String aFloat, ParseException e) {
}
});
but I have no idea how to pass a bitmap in hashmap params.
I already searched the internet, but nothing that I found in helped, the links that refer to something useful, is already old and outdated, from the epoch of the old parse ...
In parse docs I found this
var base64 = "V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=";
var file = new Parse.File("myfile.txt", { base64: base64 });
Which made me confused because I do not know if the 2 "base64" parameters refer to variable or base64 type
Should I convert my bitmap to base64 and send it as parameter to the cloud code?
If you have been through this and know how, I will be very happy to know your solution.
Thank you!
you need convert your image bitmap for base64 like that:
Bitmap bitmap = ((BitmapDrawable) img.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte [] byteArrayPhotoUpdate = stream.toByteArray();
String encodedfile = new String(Base64.encodeBase64(byteArrayPhotoUpdate), "UTF-8");
And then, send your string base64 in params, like that:
HashMap<String, String> params = new HashMap();
params.put("fileInfo",encodedfile);
ParseCloud.callFunctionInBackground("saveParseUserInfo", params, new FunctionCallback<String>() {
#Override
public void done(String aFloat, ParseException e) {
Log.i("ewaeaweaweaweawe", "done: " + aFloat);
}
});
Now in your cloud code, use that:
Parse.Cloud.define("saveParseUserInfo", function(request, response) {
var userId = request.user.id;
var base64 = request.params.fileInfo;
var userClass = Parse.Object.extend("User");
//create a user object to set ACL
var userObject = userClass.createWithoutData(userId);
//create new ParseObject
var userPublicClass = Parse.Object.extend("userPublic");
var userPublic = new userPublicClass();
var aclAction = new Parse.ACL(userObject);
aclAction.setPublicReadAccess(true);
userPublic.setACL(aclAction);
userPublic.set("name", "name random");
userPublic.set("username", "username_random");
//Now create a Parse File object
var file = new Parse.File("photo.jpeg", { base64: base64 });
//set file object in a colum profile_picture
userPublic.set("profile_picture",file);
//save
userPublic.save(null, { useMasterKey: true,
success: function(actionSuccess) {
response.success("saved!!");
},
error: function(action, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
response.error(error.message);
}
});
});
I hope it's help you.
This answer works if you do not wish to use Base64 that requires API 26 and above for android.
I know João Armando has answered this question, but this is for the benefit of others who, like me, are supporting versions before API 26 for Android.
P.S. The Base64.encodeBase64(...) is deprecated and Base64.getEncoder()... is used now, which requires API 26.
There are 3 key parts to the solution:
Convert your bitmap to byteArray
Send this byteArray directly as params when calling your cloud function
Format this byteArray in cloud code itself
In Android:
Convert bitmap to byte[]
Bitmap bitmap = <Your source>;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Send as params when calling cloud function
HashMap<String, Object> params = new HashMap<>();
params.put("imageInByteArray", byteArray);
ParseCloud.callFunctionInBackground("yourCloudFunction", params, new FunctionCallback<Map>() {
#Override
public void done(Map object, ParseException e) {
if(e == null){
// Success
} else {
// Failed
}
}
});
In cloud function/code
Depends on the version of javascript you use, the codes may differ. I am using a backend-as-a-service provider, which has improved from promises-related codes. The logic should still be applicable regardless.
Parse.Cloud.define("reportId", async request => {
// Retrieve and set values from client app
const imageInByteArray = request.params.imageInByteArray;
// Format as ParseFile
var file = new Parse.File("image.png", imageInByteArray);
// Initialize your class, etc.
....
// Save your object
await yourImageObject.save(null, {useMasterKey:true});
});

Sending Large file after converting to json to Action in MVC controller

I am reading a file in bytes using ReadAllBytes() method. Then convert these bytes to base64. Then send this base64 string as a part of JSON. On server side (which is MVC action) I receive the JSON and convert the base64 into bytes and then save it.
Small files in KB are transferring very fast and saving in temp folder. But the files in MB is not transferring at all.
I have set maxrequestlength, execution timeout done every thing with web config and even test by using httpwebrequest.keepalive = true and false.... but still all in vain. I can't send file chunks because its not the requirement. Want to send a Complete file at once...
byte[] b = File.ReadAllBytes("D://test.pdf");
string convert = Convert.ToBase64String(b);
Customer cs = new Customer();
cs.JsonString = convert;
JavaScriptSerializer js = new JavaScriptSerializer();
js.MaxJsonLength = Int32.MaxValue;
string json = js.Serialize(cs);
var request (HttpWebRequest)WebRequest.Create("http://localhost:46360/Home/Tester");
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.ContentLength = (json.Length);
request.KeepAlive = false;
request.Timeout = System.Threading.Timeout.Infinite;
request.Accept = "Accept=application/json";
request.SendChunked = false;
request.AllowWriteStreamBuffering = false;
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Close();
}
var response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}

Categories

Resources