mrh
mrh

Reputation: 917

Upload HTML5 canvas image to server Angular2/Spring Boot

I'm trying to upload HTML5 canvas image to server. Unfortunately when I convert canvas to blob and upload it to server I'm unable to open image.

My implementation is working fine with following scenario a):

  1. Right click on canvas and Save as image to disk
  2. Select canvas image file form disk via input form with type="file"
  3. Send file selected in form via AJAX in FormData object
  4. Read upload file

Desired scenario b):

  1. Get image data directly from canvas
  2. Send canvas data via AJAX in FormData object
  3. Read upload file

When I open png file upload directly from canvas (scenario b) image is blank but I can see it has correct width and height. When I compare content with correct file in notepad files have the same begging/end but are different in the middle. The only difference in the requests is Content-Length.

Technology Stack: Angular 2.4.6 Spring Boot 1.5.2

Scenario a) with file upload:

var files = event.srcElement.files;
let formData = new FormData();
formData.append('file', files[0], files[0].name);
let headers = new Headers();
headers.append('Authorization', currentUser.token);
let options = new RequestOptions({ headers });
this.http.post(this.apiUrl, formData, options)
    .map((response: Response) => {
        return response;
    })
    .catch(this.handleError);

Scenario a) request:

Request URL:http://localhost:8080/public/api/image
Request Method:POST
Status Code:200 
Remote Address:[::1]:8080
Referrer Policy:no-referrer-when-downgrade
Response Headers
    view source
    Access-Control-Allow-Credentials:true
    Access-Control-Allow-Origin:http://localhost:3000
    Cache-Control:no-cache, no-store, max-age=0, must-revalidate
    Content-Length:0
    Content-Type:application/json;charset=ISO-8859-1
    Date:Fri, 21 Apr 2017 07:11:09 GMT
    Expires:0
    Pragma:no-cache
    Vary:Origin
    X-Content-Type-Options:nosniff
    X-Frame-Options:DENY
    X-XSS-Protection:1; mode=block
Request Headers
    view source
    Accept:application/json, text/plain, */*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.8,pl;q=0.6
    Authorization:eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZGllbmNlIjoid2ViIiwiY3JlYXRlZCI6MTQ5MjU0Nzc5OTYxMiwiZXhwIjoxNDkzMTUyNTk5fQ.YKhBf1bOS-egqLahtIFWI5t2vrAEbwHss96itIO8HanKU0V38XdOOY-ZJV41wE5oSqmOoGVUYXJMoxXYrLOzXw
    Connection:keep-alive
    Content-Length:25242
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryWh6h4VZ1UIs13Tal
    Host:localhost:8080
    Origin:http://localhost:3000
    Referer:http://localhost:3000/
    User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
    Request Payload
    ------WebKitFormBoundaryWh6h4VZ1UIs13Tal
    Content-Disposition: form-data; name="file"; filename="download.png"
    Content-Type: image/png


------WebKitFormBoundaryWh6h4VZ1UIs13Tal--

HERE IS THE PROBLEM Scenario b) with canvas content:

let canvas = <HTMLCanvasElement> document.getElementById('main_canvas_container').firstElementChild;
        canvas.toBlob((blob) => {
    let formData = new FormData();
    formData.append('file', blob, 'file.png');
    let headers = new Headers();
    headers.append('Authorization', currentUser.token);
    let options = new RequestOptions({ headers });
    this.http.post(this.apiUrl, formData, options)
        .map((response: Response) => {
            return response;
        })
        .catch(this.handleError);
}

Scenario b) request:

Request URL:http://localhost:8080/public/api/image
Request Method:POST
Status Code:200 
Remote Address:[::1]:8080
Referrer Policy:no-referrer-when-downgrade
Response Headers
    view source
    Access-Control-Allow-Credentials:true
    Access-Control-Allow-Origin:http://localhost:3000
    Cache-Control:no-cache, no-store, max-age=0, must-revalidate
    Content-Length:0
    Content-Type:application/json;charset=ISO-8859-1
    Date:Fri, 21 Apr 2017 07:00:17 GMT
    Expires:0
    Pragma:no-cache
    Vary:Origin
    X-Content-Type-Options:nosniff
    X-Frame-Options:DENY
    X-XSS-Protection:1; mode=block
Request Headers
    view source
    Accept:application/json, text/plain, */*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.8,pl;q=0.6
    Authorization:eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZGllbmNlIjoid2ViIiwiY3JlYXRlZCI6MTQ5MjU0Nzc5OTYxMiwiZXhwIjoxNDkzMTUyNTk5fQ.YKhBf1bOS-egqLahtIFWI5t2vrAEbwHss96itIO8HanKU0V38XdOOY-ZJV41wE5oSqmOoGVUYXJMoxXYrLOzXw
    Connection:keep-alive
    Content-Length:11552
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundarylO2dld6ISjr1W9E6
    Host:localhost:8080
    Origin:http://localhost:3000
    Referer:http://localhost:3000/
    User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
    Request Payload
    ------WebKitFormBoundarylO2dld6ISjr1W9E6
    Content-Disposition: form-data; name="file"; filename="file.png"
    Content-Type: image/png


------WebKitFormBoundarylO2dld6ISjr1W9E6--

Server side:

@PostMapping("/public/api/image")
public ResponseEntity<String> handleFileUpload(@RequestParam MultipartFile file) {
   try {
       Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
   } catch (IOException e) {
       throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
   }
   return ResponseEntity.ok("");
}

Upvotes: 0

Views: 1776

Answers (1)

mrh
mrh

Reputation: 917

It turned out that it is an issue with framework responsible for rendering content in my canvas (Blend4Web). I was able to upload file without any problems when I fetched blob object directly from method provided by the framework. Code I shared is working properly, so it can be used as a reference. I apologize to those who devote time to analyze it.

Upvotes: 1

Related Questions