Upload File Angular 2 - rest

Currently playing around with Angular 2 RC.
Is there any tutorial/article that would help me understand uploading a file to the back-end via a REST call?
I've been through this, but it feels like there should be a more convenient way of doing it.

If you wait for RC2, you will have the ability to use other payloads than text ones.
For example Blob ones:
var headers = new Headers({'Content-Type': 'text/css'});
var body = new Blob(['body { color: red; }']);
return this.http.post('/url', body, { headers });
Arraybuffer ones:
var headers = new Headers({'Content-Type': 'text/css'});
var body = new ArrayBuffer(512);
var longInt8View = new Uint8Array(body);
for (var i = 0; i < longInt8View.length; i++) {
longInt8View[i] = i % 255;
}
return this.http.post('/url', body, { headers });
FormData ones:
var body = new FormData();
body.append('test1', 'val1');
body.append('test2', 123456);
var blob = new Blob(['body { color: red; }'], {type: 'text/css'});
body.append("userfile", blob);
return this.http.post('/url', body, { headers });
It would much easier to handle binary content for HTTP requests. Right now, it's difficult (and hacky) since Angular2 only accepts text payloads as input.

Related

How to do a preprocessing on tiles of a TileLayer before displaying them on Leaflet?

I have a large image that I broke up in 256x256 tiles using gdal2tiles.py.
I display it on leaflet as a L.tileLayer. It works fine.
Now, I'd like to preprocess the 256x256 tiles before they are rendered in tileLayer.
I need to apply an algorithm on these stored tiles, and the algorithm generates tiles of same size, but with different content. It can looks like changing stored tiles content dynamically.
Is it possible to replace tiles that are in TileLayer with processed tiles ?
How should I proceed ?
I would like to process these tiles only once, so I guess I should take advantage of caching.
#IvanSanchez thank you for your answer.
I created a new tileLayer allowing to call a rest API doing predictions on tiles (taking and returning a base64-encoded PNG image).
/*
* L.TileLayer.Infer, inspired by L.TileLayer.PixelFilter (https://github.com/GreenInfo-Network/L.TileLayer.PixelFilter/)
*/
L.tileLayerInfer = function (url, options) {
return new L.TileLayer.Infer(url, options);
}
L.TileLayer.Infer = L.TileLayer.extend({
// the constructor saves settings and throws a fit if settings are bad, as typical
// then adds the all-important 'tileload' event handler which basically "detects" an unmodified tile and performs the pxiel-swap
initialize: function (url, options) {
L.TileLayer.prototype.initialize.call(this, url, options);
// and add our tile-load event hook which triggers us to do the infer
this.on('tileload', function (event) {
this.inferTile(event.tile);
});
},
// extend the _createTile function to add the .crossOrigin attribute, since loading tiles from a separate service is a pretty common need
// and the Canvas is paranoid about cross-domain image data. see issue #5
// this is really only for Leaflet 0.7; as of 1.0 L.TileLayer has a crossOrigin setting which we define as a layer option
_createTile: function () {
var tile = L.TileLayer.prototype._createTile.call(this);
tile.crossOrigin = "Anonymous";
return tile;
},
// the heavy lifting to do the pixel-swapping
// called upon 'tileload' and passed the IMG element
// tip: when the tile is saved back to the IMG element that counts as a tileload event too! thus an infinite loop, as wel as comparing the pixelCodes against already-replaced pixels!
// so, we tag the already-swapped tiles so we know when to quit
// if the layer is redrawn, it's a new IMG element and that means it would not yet be tagged
inferTile: function (imgelement) {
// already processed, see note above
if (imgelement.getAttribute('data-InferDone')) return;
// copy the image data onto a canvas for manipulation
var width = imgelement.width;
var height = imgelement.height;
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
context.drawImage(imgelement, 0, 0);
// encode image to base64
var uri = canvas.toDataURL('image/png');
var b64 = uri.replace(/^data:image.+;base64,/, '');
var options = this.options;
// call to Rest API
fetch('/api/predict', {
method: 'POST',
mode: 'no-cors',
credentials: 'include',
cache: 'no-cache',
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
'image': [b64]
})
})
.then((response) => response.json())
.then((responseJson) => {
// Perform success response.
const obj = JSON.parse(responseJson);
image = "data:image/png;base64," + obj["predictions"][0];
var img = new Image();
img.onload = function() {
// draw retrieve image on tile (replace tile content)
context.globalAlpha = options.opacity
context.drawImage(img, 0, 0, canvas.width, canvas.height);
}
img.src = image;
imgelement.setAttribute('data-InferDone', true);
imgelement.src = image;
})
.catch((error) => {
console.log(error)
});
}
});

Ionic 3 image broken when save without run livereload

I get base64 string from take picture by camera. After that I save it into externalRootDirectory, everything works fine when I use ionic cordova run android -l -c.
But when I use ionic cordova run android the image file was broken.
This is my code:
b64toBlob(b64Data, contentType, sliceSize) {
var contentType = contentType || '';
var sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data.replace(/^data:image\/(png|jpeg|jpg);base64,/, ''));
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}
savebase64AsFile(folderPath, fileName, base64, contentType){
var DataBlob = this.b64toBlob(base64,contentType,512);
this.file.writeFile(folderPath, fileName, DataBlob).catch(e => console.log('File didn\'t save: ' + e.message));
}
saveImage(){
this.savebase64AsFile(folderPath, nameFile, base, this.image.type);
}
What you are experiencing is a problem with the Content Security Policy. When you load with live-reload it's like a web, but without it load like a direct file and then need some policy to load some contents.
Try adding this in index.html
<meta http-equiv="Content-Security-Policy" content="img-src: 'self' blob: ;"/>
Check this links for any other load resource problem:
Whitelists
Content-security-policy refused to load image
I make a test project and I can get the blob load into a img from a url with this way:
Make a new pipeline class
#Pipe({name: 'safeBlob'})
export class SafeBlob{
constructor(private sanitizer:DomSanitizer){}
transform(html) {
return this.sanitizer.bypassSecurityTrustResourceUrl(html);
}
}
Then in your img:
<img [src]="imageInBlobObjectUrl | safeBlob" alt="Blob image">
Angular2 Base64 sanitizing unsafe URL value

How to remove L.rectangle(boxes[i])

I few days ago I implement a routingControl = L.Routing.control({...}) which works perfect for my needs. However I need for one of my customer also the RouteBoxer which I was also able to implement it. Now following my code I wants to remove the boxes from my map in order to draw new ones. However after 2 days trying to find a solution I've given up.
wideroad is a param that comes from a dropdown list 10,20,30 km etc.
function routeBoxer(wideroad) {
this.route = [];
this.waypoints = []; //Array for drawBoxes
this.wideroad = parseInt(wideroad); //Distance in km
this.routeArray = routingControl.getWaypoints();
for (var i=0; i<routeArray.length; i++) {
waypoints.push(routeArray[i].latLng.lng + ',' + routeArray[i].latLng.lat);
}
this.route = loadRoute(waypoints, this.drawRoute);
}; //End routeBoxer()
drawroute = function (route) {
route = new L.Polyline(L.PolylineUtil.decode(route)); // OSRM polyline decoding
boxes = L.RouteBoxer.box(route, this.wideroad);
var bounds = new L.LatLngBounds([]);
for (var i = 0; i < boxes.length; i++) {
**L.rectangle(boxes[i], {color: "#ff7800", weight: 1}).addTo(this.map);**
bounds.extend(boxes[i]);
}
console.log('drawRoute:',boxes);
this.map.fitBounds(bounds);
return route;
}; //End drawRoute()
loadRoute = function (waypoints) {
var url = '//router.project-osrm.org/route/v1/driving/';
var _this = this;
url += waypoints.join(';');
var jqxhr = $.ajax({
url: url,
data: {
overview: 'full',
steps: false,
//compression: false,
alternatives: false
},
dataType: 'json'
})
.done(function(data) {
_this.drawRoute(data.routes[0].geometry);
//console.log("loadRoute.done:",data);
})
.fail(function(data) {
//console.log("loadRoute.fail:",data);
});
}; //End loadRoute()
Well, my problem is now how to remove previously drawn boxes in order to draw new ones because of changing the wideroad using a dropdown list. Most of this code I got from the leaflet-routeboxer application.
Thanks in advance for your help...
You have to keep a reference to the rectangles so you can manipulate them (remove them) later. Note that neither Leaflet nor Leaflet-routeboxer will do this for you.
e.g.:
if (this._currentlyDisplayedRectangles) {
for (var i = 0; i < this._currentlyDisplayedRectangles.length; i++) {
this._currentlyDisplayedRectangles[i].remove();
}
} else {
this._currentlyDisplayedRectangles = [];
}
for (var i = 0; i < boxes.length; i++) {
var displayedRectangle = L.rectangle(boxes[i], {color: "#ff7800", weight: 1}).addTo(this.map);
bounds.extend(boxes[i]);
this._currentlyDisplayedRectangles.push(displayedRectangle);
}
If you don't store a reference to the L.rectangle() instance, you obviously won't be able to manipulate it later. This applies to other Leaflet layers as well - not storing explicit references to Leaflet layers is a usual pattern in Leaflet examples.

Connecting a simple gain node to Web Audio API file buffers

I can't seem to understand why this isn't working. I have no errors.I have done this using oscillators and it works fine. FYI this is a continuation of this thread:
Using Web Audio API to assign two sounds to two Divs and play each independently via a click event with javascript
Code:
<div id="divElement"></div>
<style>
#divElement{
background-color: orange;
width:70px;
height:100px;
left:143px;
}
</style>
<script>
var context = new webkitAudioContext(),
savedBuffer;
var playAudioFile = function () {
var source = context.createBufferSource();
var gainNode = context.createGainNode();
source.buffer = savedBuffer;
// START OF PROBLEM AREA: Gain not working but file still plays with no errors.
source.connect(gainNode);
gainNode.connect(context.destination);
gainNode.gain = 0;
// END OF PROBLEM AREA
source.noteOn(0); // Play sound immediately
};
var request = new XMLHttpRequest();
request.open('get', 'audio/A.mp3', true);
request.responseType = 'arraybuffer';
request.onload = function () {
context.decodeAudioData(request.response,
function(incomingBuffer) {
savedBuffer = incomingBuffer;
var divElement = document.getElementById("divElement");
divElement.addEventListener("click", playAudioFile , false);
}
);
};
request.send();
</script>
Try gainNode.gain.value = 0 instead. gainNode.gain is an AudioGain object, which has the attribute value.
http://www.w3.org/TR/webaudio/#AudioGainNode

how to ask for new value before showing to the user?

I found this sample code where i can replace something automatically in the page
// If content-type is HTML, then remove all DIV tags
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "html")){
// Remove any compression or chunking
oSession.utilDecodeResponse();
var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
// Replace all instances of the DIV tag with an empty string
var oRegEx = /<div[^>]*>(.*?)<\/div>/gi;
oBody = oBody.replace(oRegEx, "");
// Set the response body to the div-less string
oSession.utilSetResponseBody(oBody);
}
But how can i ask for the new value, instead of replacing it automatically?
See if this works for you
if (oSession.uriContains("/yoururl/here")) {
oSession.utilDecodeResponse();
var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
var oRegEx = /this text will be replaced everywhere/gi;
var mydefaulttext = 'new text';
var mymsgbox = FiddlerScript.prompt('Lets change something', mydefaulttext);
oBody = oBody.replace(oRegEx, mymsgbox);
oSession.utilSetResponseBody(oBody);
}
OnBeforeResponse