上传 HTML5 canvas 图像到服务器 Angular2/Spring 启动
Upload HTML5 canvas image to server Angular2/Spring Boot
我正在尝试将 HTML5 canvas 图片上传到服务器。
不幸的是,当我将 canvas 转换为 blob 并将其上传到服务器时,我无法打开图像。
我的实现在以下场景 a) 中运行良好:
- 右键单击 canvas 并另存为图像到磁盘
- Select canvas 图像文件磁盘通过类型为"file"
的输入表单
- 通过 AJAX 在 FormData 对象中发送在表单中选择的文件
- 读取上传文件
期望的场景 b):
- 直接从canvas
获取图像数据
- 通过 FormData 对象中的 AJAX 发送 canvas 数据
- 读取上传文件
当我打开直接从 canvas 上传的 png 文件时(场景 b)图像是空白的,但我可以看到它具有正确的宽度和高度。
当我将内容与记事本文件中的正确文件进行比较时,文件具有相同的 begging/end 但中间不同。
请求的唯一区别是 Content-Length。
技术栈:
Angular2.4.6
Spring 引导 1.5.2
场景 a) 文件上传:
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);
场景a)请求:
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--
这是问题场景 b) canvas 内容:
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);
}
场景b)请求:
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--
服务器端:
@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("");
}
事实证明,这是负责在我的 canvas (Blend4Web) 中呈现内容的框架的问题。当我直接从框架提供的方法中获取 blob 对象时,我能够毫无问题地上传文件。我分享的代码运行正常,可以作为参考。对花时间分析的人表示歉意
我正在尝试将 HTML5 canvas 图片上传到服务器。 不幸的是,当我将 canvas 转换为 blob 并将其上传到服务器时,我无法打开图像。
我的实现在以下场景 a) 中运行良好:
- 右键单击 canvas 并另存为图像到磁盘
- Select canvas 图像文件磁盘通过类型为"file" 的输入表单
- 通过 AJAX 在 FormData 对象中发送在表单中选择的文件
- 读取上传文件
期望的场景 b):
- 直接从canvas 获取图像数据
- 通过 FormData 对象中的 AJAX 发送 canvas 数据
- 读取上传文件
当我打开直接从 canvas 上传的 png 文件时(场景 b)图像是空白的,但我可以看到它具有正确的宽度和高度。 当我将内容与记事本文件中的正确文件进行比较时,文件具有相同的 begging/end 但中间不同。 请求的唯一区别是 Content-Length。
技术栈: Angular2.4.6 Spring 引导 1.5.2
场景 a) 文件上传:
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);
场景a)请求:
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--
这是问题场景 b) canvas 内容:
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);
}
场景b)请求:
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--
服务器端:
@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("");
}
事实证明,这是负责在我的 canvas (Blend4Web) 中呈现内容的框架的问题。当我直接从框架提供的方法中获取 blob 对象时,我能够毫无问题地上传文件。我分享的代码运行正常,可以作为参考。对花时间分析的人表示歉意