Get me outta here!

How to convert base64 string to byte array in angularjs

/** Process the type1 base64 string **/
var myBaseString = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkYAAA.....";

// Split the base64 string in data and contentType
var block = myBaseString.split(";");

// get the real base64 content of the file
var realData = block[1].split(",")[1];// In this case "iVBORw0KGg...."
Advertisements

How to create an image file from a base64 string

Convert a base64 to a file with Javascript and Cordova is more easier than you think. However, you can’t directly use the cordova-plugin-file to write your string into a file because it is not supported. But it accepts binary data, and that’s the way in which we are going to save our image. To create a image file from a base64 string, we’ll convert it into a Blob using a non-conventional method.

Requirements

As we are handling files, you need to have the cordova-file-plugin in your project. To install this plugin use :

cordova plugin add cordova-plugin-file

If you don’t know anything about this plugin, read more about how it works in the official repository here.

Implementation

To convert a base64 string into a image file, we are going to require the following 2 methods.

/**
 * Convert a base64 string in a Blob according to the data and contentType.
 * 
 * @param b64Data {String} Pure base64 string without contentType
 * @param contentType {String} the content type of the file i.e (image/jpeg - image/png - text/plain)
 * @param sliceSize {Int} SliceSize to process the byteCharacters
 * @see http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
 * @return Blob
 */
function b64toBlob(b64Data, contentType, sliceSize) {
        contentType = contentType || '';
        sliceSize = sliceSize || 512;

        var byteCharacters = atob(b64Data);
        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);
        }

      var blob = new Blob(byteArrays, {type: contentType});
      return blob;
}

/**
 * Create a Image file according to its database64 content only.
 * 
 * @param folderpath {String} The folder where the file will be created
 * @param filename {String} The name of the file that will be created
 * @param content {Base64 String} Important : The content can't contain the following string (data:image/png[or any other format];base64,). Only the base64 string is expected.
 */
function savebase64AsImageFile(folderpath,filename,content,contentType){
    // Convert the base64 string in a Blob
    var DataBlob = b64toBlob(content,contentType);
    
    console.log("Starting to write the file :3");
    
    window.resolveLocalFileSystemURL(folderpath, function(dir) {
        console.log("Access to the directory granted succesfully");
		dir.getFile(filename, {create:true}, function(file) {
            console.log("File created succesfully.");
            file.createWriter(function(fileWriter) {
                console.log("Writing content to file");
                fileWriter.write(DataBlob);
            }, function(){
                alert('Unable to save file in path '+ folderpath);
            });
		});
    });
}

The cordova file writer provided by the cordova-file-plugin doesn’t support write files with base64, therefore we are going to use a little trick. The base64 string will be processed and converted into a writable Blob.

Using savebase64AsImageFile method

The method is well explained in the snippet, to test it you can test the following code in your project, it should create the following image in your root directory.

Base64 to image file in cordova

// Remember to execute this after the onDeviceReady event

// If your base64 string contains "data:image/png;base64,"" at the beginning, keep reading.
var myBase64 = "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";
// To define the type of the Blob
var contentType = "image/png";
// if cordova.file is not available use instead :
// var folderpath = "file:///storage/emulated/0/";
var folderpath = cordova.file.externalRootDirectory;
var filename = "ourcodeworld.png";

savebase64AsImageFile(folderpath,filename,myBase64,contentType);

According to your case and base64 image format you can have 2 types of base64 strings :

// This type is common when using toDataUrl() on a canvas.
var type1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkYAAAD.................";
// The plain base64 content of a file, maybe retrieven from a server ?
var type2 = "iVBORw0KGgoAAAANSUhEUgAAAkYAAAD.................";

Saving base64 type 1

As this string already contains the content type that requires the function, we only need to process the string and retrieve in different variables the content and the content type (image/png or image/jpeg etc).

/** Process the type1 base64 string **/
var myBaseString = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkYAAA.....";

// Split the base64 string in data and contentType
var block = myBaseString.split(";");
// Get the content type
var dataType = block[0].split(":")[1];// In this case "image/png"
// get the real base64 content of the file
var realData = block[1].split(",")[1];// In this case "iVBORw0KGg...."

// The path where the file will be created
var folderpath = "file:///storage/emulated/0/";
// The name of your file, note that you need to know if is .png,.jpeg etc
var filename = "myimage.png";

savebase64AsImageFile(folderpath,filename,realData,dataType);

Saving base64 type 2

With this format, you need to find out by yourself the content type of the base64 because we have only the data.

// The base64 content
var myBase64 = "iVBORw0KGgoAAAANSUhEUgAAANIAAAD......";
// To define the type of the Blob, you need to get this value by yourself (maybe according to the file extension)
var contentType = "image/png";
// The path where the file will be saved
var folderpath = "file:///storage/emulated/0/";
// The name of your file
var filename = "myphoto.png";

savebase64AsImageFile(folderpath,filename,myBase64,contentType);

Have fun

Ng-click doesn’t work inside ng-repeat

Instead of this:

<li ng-repeat="e in events">
  <a ng-click="triggerTitle=e.name; triggerEvent = e.action;">{{e.action}} {{e.name}}</a>
</li>

Just do this:

<li ng-repeat="e in events">
  <a ng-click="$parent.triggerTitle=e.name; $parent.triggerEvent = e.action;">{{e.action}} {{e.name}}</a>
</li>

ng-repeat creates a new scope, you can use $parent to access the parent scope from inside the ng-repeat block.

Easy Pagination with Spring Boot.

In this short tutorial , we’ll see how easy it is to set up Pagination in a Spring Boot app .

Setup

We use Spring Boot 1.3.3.RELEASE , with MySQL as the Database and Spring Data JPA abstraction to work with MySQL. Indeed ,it is the Spring Data JPA module that makes it so easy to set up Pagination in a Spring boot app in the first place.

Scenario

We expose an endpoint /persons . It will return a List of persons and other paging info(which we would see in a minute) based on the page and size parameters that were passed along with it.

For instance , /persons?page=0&size=3 would return a batch of the first 3 persons from the database /persons?page=1&size=3 would return the next batch .

To begin with, we create a domain Person class .

@Entity
@Table
class Person {
	@Id
	@GeneratedValue
	Integer id
	
	@Column
	String name
	
	@Column
	Integer age
}

This is how our Controller looks like .

@RestController
class PersonController {
	
	final PersonService personService
	
	@Autowired
	def PersonController( PersonService personService ){
		this.personService = personService
	}
	
	@RequestMapping(value="/persons",method=RequestMethod.GET)
	Page<Person> list( Pageable pageable){
		Page<Person> persons = personService.listAllByPage(pageable)
		persons
	} 
}

Notice that we haven’t passed RequestParams to our handler method . When the endpoint /persons?page=0&size=3is hit, Spring would automatically resolve the page and size parameters and create a Pageable instance . We would then pass this Pageable instance to the Service layer ,which would pass it to our Repository layer .

Next,we create a PersonRepository class to interact with the database.

interface PersonRepository extends PagingAndSortingRepository<Person,Integer> {

}

The PersonRepository class is just an interface. This might be weird for those coming from traditional Spring MVC world wherein you had to write implementation classes , and interacted with the database using Hibernate. Well, you don’t need to do that anymore. The PagingAndSortingRepository extends the CrudRepository , thereby adding Paging capabilities .

Now all we need to do is to create a PersonService interface and PersonServiceImpl to expose the repository.

interface PersonService {
	Page<Person> listAllByPage(Pageable pageable)
}
@Service
@Transactional
class PersonServiceImpl implements PersonService {

	final PersonRepository personRepository
	
	@Autowired
	def PersonServiceImpl(PersonRepository personRepository){
		this.personRepository = personRepository
	}
	
	@Override
	 Page<Person> listAllByPage(Pageable pageable) {
		 personRepository.findAll(pageable)
	}
}

This is all, really ! Let’s test it out . I created a test class to insert a batch of 20 Person objects . You can do this manually ofcourse.

@RunWith(SpringJUnit4ClassRunner)
@SpringApplicationConfiguration(classes = SampleBootPaginationApplication)
@WebAppConfiguration
class SampleBootPaginationApplicationTests {
	
	@Autowired
	PersonRepository personRepository
	 
	@Test
	void contextLoads() { 
		def person 
		(1..20).each{
			person = new Person(name:"John $it", age : 22)
			personRepository.save(person)
		}
	}
}

Great,we’re all done . Let’s hit the endpoint with Postman .

pagination_!

The snapshot doesn’t display the entire JSON. So here it is .

{
  "content": [
    {
      "id": 1,
      "name": "John 1",
      "age": 22
    },
    {
      "id": 2,
      "name": "John 2",
      "age": 22
    },
    {
      "id": 3,
      "name": "John 3",
      "age": 22
    }
  ],
  "last": false,
  "totalElements": 20,
  "totalPages": 7,
  "size": 3,
  "number": 0,
  "sort": null,
  "first": true,
  "numberOfElements": 3
}

You can download the sample here

Angularjs file upload and download using springboot,gradle and mysql

fileupload.html :

<html>
<head>
<!– <link rel=”stylesheet” href=”plugins/css/bootstrap.min.css”> –>
https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js
http://app-module.js
http://fileUpload.js
<!– Latest compiled and minified CSS –>

<link rel=”stylesheet”
href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css&#8221;
integrity=”sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u”
crossorigin=”anonymous”>

<!– Optional theme –>
<link rel=”stylesheet”
href=”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css&#8221;
integrity=”sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp”
crossorigin=”anonymous”>

<!– Latest compiled and minified JavaScript –>
https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js
</head>
<body ng-app=”myApp”>
<form ng-controller=”myCtrl”>

<h2>File Upload</h2>
<input type=”file” file-model=”files” multiple />
<button class=”btn btn-primary” ng-click=”uploadFile()”>upload
me</button>
</br> </br> </br>
<h2>Saved images</h2>
</br>
<table class=”table table-bordered”>
<thead>
<tr>
<th>#</th>
<th>File Name</th>
<th>Download</th>
</tr>
</thead>
<tbody>
<tr ng-repeat=”image in images track by $index”>
<td>{{getRowNo($index)}}</td>
<td>{{ image.fileName }}</td>
<td><button class=”btn btn-primary”
ng-click=”downloadImage(image)”>download</button></td>
</tr>
</tbody>
</table>

< PREV
Page {{curPage + 1}} of {{totalPages}}

NEXT >

</form>

</body>
</html>

fileupload.js :

app.controller(‘myCtrl’, [‘$scope’, ‘$http’,’$timeout’, function($scope, $http,$timeout){
$http.get(‘http://localhost:6061/file/getall&#8217;).success(function(data){
console.log(“success”);
$scope.images=data.fileNames;
})
$scope.convertToByteArray = function(file,dataObj) {

if(file != null || file != undefined){
var reader = new FileReader();
reader.onload = function(event){
var contents = event.target.result;
var uploadedFile = btoa(contents);
dataObj.data = uploadedFile;
$http.post(‘http://localhost:6061/file/doUpload&#8217;,dataObj,
{
headers: {‘Content-Type’: ‘application/json’}
}).success(function(d){
console.log(d);
})
};
reader.readAsBinaryString(file);
}
}
$scope.downloadImage=function(fileName){
$http({
url: ‘http://localhost:6061/file/download/:fileName&#8217;,
method: “GET”,
params: {
fileName: fileName
},
responseType: ‘arraybuffer’
}).success(function(data){
console.log(data);
var url = URL.createObjectURL(new Blob([data]));
var a = document.createElement(‘a’);
a.href = url;
a.download = fileName;
a.target = ‘_blank’;
a.click();
})
}
$scope.uploadFile=function(){

console.log($scope.files);
for(var i=0;i<$scope.files.length;i++){
var uploadingFile={};
uploadingFile.fileName=$scope.files[i].name;
uploadingFile.fileContentType=$scope.files[i].type;
$scope.convertToByteArray($scope.files[i],uploadingFile);
}
}
}]);

app-module.js:

var app = angular.module(‘myApp’, []).directive(‘fileModel’, [‘$parse’, function ($parse) {
return {
restrict: ‘A’,
link: function(scope, element, attrs) {
element.bind(‘change’, function(){
$parse(attrs.fileModel).assign(scope,element[0].files)
scope.$apply();
});
}
};
}])

FileController.java:

package com.app.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.PathParam;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.app.dto.FileUploadDto;
import com.app.model.UploadFile;
import com.app.repo.FileUploadRepo;

/**
* Handles requests for the file upload page.
*/
@RequestMapping(value = “/file”)
@RestController
public class FileController {
@Autowired
private FileUploadRepo fileUploadRepo;

@RequestMapping(value = “/doUpload”, method = RequestMethod.POST)
public String handleFileUpload(@RequestBody FileUploadDto fileUploadDto) throws Exception {

if(fileUploadDto.getFileName()==null){
return “File name is empty”;
}
System.out.println(“Saving file: ” + fileUploadDto.getFileName());
UploadFile uploadFile=new UploadFile();
uploadFile.setFileName(fileUploadDto.getFileName());
uploadFile.setData(fileUploadDto.getData());
uploadFile.setFileContentType(fileUploadDto.getFileContentType());
fileUploadRepo.save(uploadFile);
return “Success”;
}
@RequestMapping(value = “/getall”, method = RequestMethod.GET)
public FileUploadDto getAll(){
FileUploadDto dto=new FileUploadDto();

List uploadFiles =fileUploadRepo.findAll();
List fileNames = new ArrayList<>();

for(UploadFile file:uploadFiles){
fileNames.add(file.getFileName());
}
dto.setFileNames(fileNames);
System.out.println(“filenames : “+fileNames);
return dto;
}

@RequestMapping(value = “/download/{fileName}”, method = RequestMethod.GET)
public void downloadImage(@RequestParam String fileName, HttpServletResponse response) {
UploadFile file=fileUploadRepo.getByFileName(fileName);
try {
response.setContentType(file.getFileContentType());

response.setHeader(“Content-Disposition”, “attachment; filename=” + file.getFileName());

response.setContentLength(file.getData().length);

response.getOutputStream().write(file.getData());

response.getOutputStream().flush();

response.getOutputStream().close();

} catch (Exception e) {
System.out.println(“Error occur during download attachment file : ” + fileName);
System.out.println(“Error : ” + e);
}
}
}

FileUploadDto.java:

package com.app.dto;

import java.util.List;

import lombok.Data;

@Data
public class FileUploadDto {

private String fileName;

private byte[] data;

private List fileNames;

private String fileContentType;

}

UploadFile.java :

package com.app.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = “FILES_UPLOAD”)
public class UploadFile implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue
@Column(name = “FILE_ID”)
private long id;

@Column(name = “FILE_NAME”)
private String fileName;

@Column(name = “FILE_CONTENT_TYPE”)
private String fileContentType;

@Column(name = “FILE_DATA”)
@Lob
private byte[] data;

}

FileUploadRepo.java:

package com.app.repo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.app.model.UploadFile;
public interface FileUploadRepo extends JpaRepository<UploadFile, Long> {

@Query(“select up from UploadFile up where up.fileName=?1”)
UploadFile getByFileName(String fileName);
}

Application.properties :

server.port=6061
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/imagedb?useSSL=false
spring.datasource.username=root
spring.datasource.password=root123

build.gradle :

buildscript {
ext {
springBootVersion = ‘1.5.1.RELEASE’
}
repositories {
mavenCentral()
}
dependencies {
classpath(“org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}”)
}
}

apply plugin: ‘java’
apply plugin: ‘eclipse-wtp’
apply plugin: ‘org.springframework.boot’
apply plugin: ‘war’

war {
baseName = ‘achyuPrj’
version = ‘0.0.1-SNAPSHOT’
}

sourceCompatibility = 1.8

repositories {
mavenCentral()
}

configurations {
providedRuntime
}

dependencies {
compile(‘com.fasterxml.jackson.core:jackson-core:2.7.2’)
compile(‘com.fasterxml.jackson.core:jackson-annotations:2.7.2’)
compile(‘com.fasterxml.jackson.core:jackson-databind:2.7.2’)
compile(‘org.springframework.boot:spring-boot-starter-data-jpa’)
compile(‘org.springframework.boot:spring-boot-starter-web’)
compile(‘mysql:mysql-connector-java’)
compile(‘org.projectlombok:lombok’)
providedRuntime(‘org.springframework.boot:spring-boot-starter-tomcat’)
testCompile(‘org.springframework.boot:spring-boot-starter-test’)
}

How to do a $http GET with some data in Angular?

If you want to pass some data on using GET method you can pass a params options on the get method of the $http service. This will be urlencode parameters

$http.get(url, {
  params: {
    query: 'hello world'
  }
} 

or

$http({
   url: url,
   method:'GET',
   params: {
     query:'Hello World'
   }
})

But, the http standars define the POST method to send data to the server. The GET is just to obtain data from it. On angular the post method:

$http({
  url: url,
  method:'POST',
  data: {
    query: 'Hello World'
  }
})

check the official docs from GET and POST