Ionic 2 binary file has different content after download - angularjs

I am using the ionic 2 framework and the cordova file plugin.
I am downloading a pdf file from a server, using the php readfile($path) method, on the client side, i am using Http from angular/http.
Now the problem is, that after the download and a save using the writeFile(path, file,data,options) method from ionic-native/file, the content of the file is not the same as the content from the server.
Notice: Left the output file and right the server version, both printed with the cat command.
I have no idea why the content is not the same.
The http call:
this.http.post(httpEndpoint + ":8280/download", data, headers).subscribe(response => {
me.proceedFile(response.text(), file, fileManager, opener);
});
Here the save:
private proceedFile(data:string, file:File, fileManager:FileManger,
opener:FileOpener) {
...
const me = this;
const putFile = function () {
fileManager.writeFile(fileManager.dataDirectory ,"data/" +
strid+"/" + file.name, data, true).then(_ => {
});
};
...
}
Regards Liz3

Related

Django FileResponse PDF - pdf font changes in frontend - (Django DRF and React.js)

I am using Django Rest Framework and React.js for my application. As part of the application I generate pdf in the backend and then send them to the frontend to be displayed. This functionality is working, if not for the fact that the font in my pdf at the front-end looks different.
In my backend I am using reportlab to generate the pdfs, using buffer = io.BytesIO() as object of reportlab.pdfgen canvas.
Then in my view, I send it via FileResponse. The font family I use id 'Roboto'.
In my frontend I then call the API via Axios and open the pdf with the following code.
const config = {
headers: {
Authorization: `Bearer ${access_token}`
}
}
const { data } = await axios.get(
`/api/my/url/`,
config
)
const file = new Blob([data], { type: "application/pdf" });
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
const pdfWindow = window.open();
pdfWindow.location.href = fileURL;
This correctly opens my pdf in a new window.
However, the font of my pdf is changed, the characters look a bit different (and utf-8 symbols are completely changed with other symbols).
When I test my API with Postman, the downloaded pdf looks exactly as it should, so I believe the problem is in the frontend.
I'm not sure what is the cause of the problem, so I would really appreciate help!

Set retry with dropzone-react-component when upload fails

In my project I'm using React-Dropzone-Component (https://github.com/felixrieseberg/React-Dropzone-Component) based on Dropzone.js.
I'm using this component because I'm developing a SharePoint webpart and there is already an example based on this solution on Microsoft PnP GitHub repository.
Anyway, the upload is working fine, but sometimes, mainly when I keep a web page opened for a couple of minutes doing nothing, I receive an error trying to upload new files. I retry an upload and it fails returning Server responded with (0) code error. I also see on Google Chrome console an ERR_CONNECTION_RESET error. If I try to upload 5 files in second instance, I get error on first 2-3 and then the remaining files works fine. Weird.
I've already investigated my network, but there are no failures. I've also tried with 3 different networks and I've received the same error.
I've also updated the component with the latest Dropzone.js (5.7.2).
This is my code:
let componentConfig = {
iconFiletypes: this.props.fileTypes.split(','),
showFiletypeIcon: true,
postUrl: _context.pageContext.web.absoluteUrl,
autoProcessQueue: true
};
var djsConfig = {
headers: {
"X-RequestDigest": digest1
},
addRemoveLinks:false
};
let myDropzone;
let eventHandlers = {
// This one receives the dropzone object as the first parameter
// and can be used to additional work with the dropzone.js
// object
init: function(dz){
myDropzone=dz;
},
sending: async function (file, xhr) {
var fileName = file.name;
fileName = fileName.replace(/[&\/\\#,+()$~%='":*?<>{}]/g, "");
if (file.size <= 10485760) {
// small upload
await web.getFolderByServerRelativeUrl("/test/"+_listName).files.add(fileName, file, true).then(_ => console.log("Ok!"));
} else {
// large upload
await web.getFolderByServerRelativeUrl("/test/"+_listName).files.addChunked(fileName, file, data => {}, true).then(_ => console.log("Ok!"));
}
},
error:function(file,error,xhr){
file.status = myDropzone.ADDED;
myDropzone.removeFile(file);
myDropzone.enqueueFile(file);
}
};
<DropzoneComponent eventHandlers={eventHandlers} djsConfig={djsConfig} config={componentConfig}>
<div className="dz-message icon ion-upload">Drop files here to upload</div>
</DropzoneComponent>
If I can't prevent this ERR_CONNECTION_RESET error, I would like to set up an automatic retry for these files. The code I've posted above is not working fine or it returns "Uncaught Error: This file can't be queued because it has already been processed or was rejected.".
Is there a solution or a good way to set up a retry?

Download large files using React and AspnetCore to open browser save (headers)

I'm struggling with the problem of downloading large files using a web API in asp net core and frontend in React.
When the file starts downloading it doesn't show the dialog browser (Save As File Dialog) until it downloads the file in memory and next gives the possibility to save it.
When the file is bigger, like 200MB, the user can't choose where to save the file before start downloading it and see the download progress in the browser tab.
This is to use with react frontend and web API in aspnet core.
After reading for some hours I couldn't find the solution.
I can't use a link to download the file because I need to authenticate with a token.
Maybe I am missing any configuration or setup in my backend/frontend?
Any suggestions or advice will be very appreciated.
The method of my web api:
[HttpGet("{fileName}")]
[Authorize]
public IActionResult GetFile(string fileName)
{
Stream stream = _fileManager.GetFileContent(fileName);
// Response...
ContentDisposition cd = new ContentDisposition("attachment")
{
FileName = fileName,
// DispositionType = "attachment; filename=" + fileName + ";",
Inline = false // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(stream, MediaTypeNames.Application.Zip);
}
The frontend using axios to get it.
async function Download() {
var authToken = await authService.Token();
console.log("calling request", process.env.REACT_APP_API_URL + "files/GetFile/iPro.zip");
if (authToken) {
BioAxios.get("/files/GetFile/file.zip", {
responseType: "blob",
headers: {
Authorization: "Bearer ".concat(authToken.access_token),
"Content-Type": "application/zip"
}
}).then(response => {
// Log somewhat to show that the browser actually exposes the custom HTTP header
console.log("Full Response", response);
// Let the user save the file.
FileSaver.saveAs(response.data, "file.zip");
});
}
}

Is there a way to dump a thousand images somewhere and extract them using REST Api?

Here is the thing:-
I have over a thousand images saved locally in my mac. I have a landing page that mocks an ecommerce deal site. It would be tedious to have to manually type in the src url in the img tag for a thousand pictures. Thus, i thought i could somehow have this images dumped in a cloud storage or something and use REST api get method to extract these images in a response.data. Then assign it to a $scope variable and use ng-repeat to bind the images in my landing page view. Is this possible? If not, what are the alternatives? SQL database?
Appreciate your help. P.S. I am totally a beginner at web development.
Install node.js. It's Javascript for a server which should make it pretty easy since you already know Javascript.
On a Mac, you can install node like this:
brew install node
Use this node.js code (credit to codepedia.com, tweaked a little by me):
//include http, fs and url module
var http = require('http'),
fs = require('fs'),
path = require('path'),
url = require('url');
imageDir = './images/';
//create http server listening on port 3333
http.createServer(function (req, res) {
//use the url to parse the requested url and get the image name
var query = url.parse(req.url,true).query;
pic = query.image;
if (typeof pic === 'undefined') {
getImages(imageDir, function (err, files) {
var imageList = JSON.stringify(files);
res.writeHead(200, {'Content-type':'application/json'});
res.end(imageList);
});
} else {
//read the image using fs and send the image content back in the response
fs.readFile(imageDir + pic, function (err, content) {
if (err) {
res.writeHead(400, {'Content-type':'text/html'})
console.log(err);
res.end("No such image");
} else {
//specify the content type in the response will be an image
res.writeHead(200,{'Content-type':'image/jpg'});
res.end(content, "binary");
}
});
}
}).listen(3333);
console.log("Server running at http://localhost:3333/");
//get the list of jpg files in the image dir
function getImages(imageDir, callback) {
var fileType = '.jpg',
files = [], i;
fs.readdir(imageDir, function (err, list) {
for(i=0; i<list.length; i++) {
if(path.extname(list[i]) === fileType) {
files.push(list[i]); //store the file name into the array files
}
}
callback(err, files);
});
}
Run this from the command line to start you new image server (assuming you named the file "server.js"):
node server.js
You should see this text appear on the command line:
Server running at http://localhost:3333/
You can quickly test it by going to this address in your browser and you should see a JSON object showing you an array of all the filenames in the "./images" directory. By the way, this program assumes you're putting the images folder in the same directory as "server.js". You can put the images directory anywhere and just change the path of the variable "imageDir".
Now you can load the list of files from Angular using this code in your controller:
$http.get("http://localhost:3333", function(data) {
$scope.images = data;
});
In your view, you can now use an ng-repeat like this to display all the images:
<div ng-repeat="image in images" style="padding: 8px">
<img src="http://localhost:3333/image={{ image }}">
</div>
Note: this will work if you run it locally on your Mac or if you upload all the images to a server on which you can use Node.js.

Angular : show image from REST Service

After reseaches and tests, I still can't show an image form ReST API on my Angular App. I have images available on my ReST web service, why do I use a ReST service? Because in order to access you need to be authenticated (I use oAuth 2 protocol). When I use POSTMan (ReST client very usefull) everything works great, the image is displayed without doing nothing. But when I try to display it with Angular after a $http it doesn't work.
Here are the headers received form the service :
Content-Length → 51756
Content-Type → image/jpeg; charset=binary
Server → Apache/2.4.9 (Win64) PHP/5.5.12
X-Powered-By → PHP/5.5.12
Here is my Angular code :
var data64 = $base64.encode(unescape(encodeURIComponent(data)));
scope.src = 'data:image/jpeg;charset=binary;base64,' + data64;
and my HTML :
<img ng-src="{{src}}" border="0" />
For information I use angular-base64 (https://github.com/ninjatronic/angular-base64) for the encodage. Without "unescape" and "encodeURIComponent" I have an error, I've tried to remove white spaces but it still doesn't work.
Thank you :)
Seems that this will not work since you tell the browser that the image data is base64 encoded, but you also transformed it with unescape and encodeURIComponent.
Why don't you fetch your image data into a binary data structure (requires a modern browser), instead of into a string:
$http.get(req, {responseType: "arraybuffer"}).
success(function(data) {
$scope.src = 'data:image/jpeg;base64,' + _arrayBufferToBase64(data);
});
_arrayBufferToBase64 is defined here.
A different approach would be to install a request interceptor, recognize the image url and add the oauth headers for this case.
I tryed this way in angular 8+ and works fine:
imageToShow: any;
createImageFromBlob(image: Blob) {
let reader = new FileReader();
reader.addEventListener("load", () => {
this.imageToShow = reader.result;
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
and also call it like this:
getImageFromService() {
this.api.getImage(key).subscribe(data => {
this.createImageFromBlob(data);
}, error => {
console.log(error);
});
}

Resources