【发布时间】:2020-05-04 06:25:59
【问题描述】:
我正在从客户端发送jpg 图像。图片以blob的形式发送。这是发送canvas图像的javascript代码
canvas.toBlob((blob) => {
this.setState({preview: blob},
() => {
console.log(blob.size);
let data = new FormData();
// const test = URL.createObjectURL(blob);
// console.log(test);
const file = new File([blob], "File name", {type: "image/png"});
data.append("file", file);
console.log(this.state.preview);
axios({
method: "POST",
data: data,
url: "/media",
headers: {
'Content-Type': 'multipart/form-data'
}
}).then().catch()
// axios.post("http://localhost:8085/api/media", data).then(r => {}).catch()
}
);
}, "image/jpg", 0)
选择的文件是jpg文件,由于某些原因被转换为canvas,然后以blob的形式发送到服务器。
这是用java编写的服务器图像处理代码:
public void uploadMedia(MultipartFile mediaFile) {
try{
BufferedImage image = ImageIO.read(mediaFile.getInputStream());
System.out.println(image.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB); //TRUE
ImageIO.write(image, "jpg", new File("/Users/puspender/Desktop/Test/image.jpg")); //BLACK IMAGE with CMYK color space
ImageIO.write(image, "png", new File("/Users/puspender/Desktop/Test/image.png"));
}catch(Exception e){}
}
如果我为ImageIO.write 选择png 格式,则图像会成功保存,但如果格式为jpg,则会保存黑色图像,并且该黑色图像的color space 会更改为CMYK。即使原始文件是RGB,我也在控制台上打印了它,然后再保存文件。
仅当在客户端上裁剪图像(或其他内容)然后从中创建canvas 并将canvas 中的blob 作为有效负载发送时,才会出现此问题。使用<input type="file />选择文件时不会出现问题
更新:按照 Mike 的要求,我阅读并重新生成了由 ImageIo 生成的黑色 jpg。结果是一样的,都是黑色的图像。
File file = new File("/location/generated_black.jpg");
BufferedImage image = ImageIO.read(file);
ImageIO.write(image, "jpg", new File("/location/from-java-main-400x400.jpg"));
我还用原始文件测试了上面的代码,当时ImageIo 正确处理了它。
我注意到一件重要的事情:黑色图像实际上不是黑色,它只是由于色彩空间的变化而受到干扰的颜色。当我将它上传到 AWS S3 时,我注意到了这一点。这是图片(CMYK)
原文件如下:
我设法正常工作。 this thread 上的一位出色的个人推荐了 this solution,它甚至运作良好。
但很少有问题保持不变:
- 为什么这只发生在
blobjavascript 发送的数据和 不是前面提到的普通文件选择器 - 为什么只在将图像格式设置为
jpg而不是png?以及为什么将color space更改为jpg为ImageIo
【问题讨论】:
-
问题:您为什么使用
toBlob()而不是canvas.toDataURL('image/jpeg'),然后将这些数据发送到您的服务器进行解包? -
因为
toDataURL生成的字符串不被服务器的MultipartFile识别,请求被认为没有对应的处理程序 -
以前我只是这样做并且得到
400错误。 -
这听起来像是你应该能够在没有客户端/服务器的情况下进行测试:如果你创建一个带有静态 main 的
Test.java,它只是读取你保存时获得的 png 文件画布到文件,然后你尝试将 ImageIO.write 为 jpg,会发生什么? (基本上,这应该很容易变成minimal reproducible example,尤其是如果这也出错了,您可以直接将该 png 添加到您的帖子中,这样人们就可以同时拥有代码和资产来重现您所看到的内容) -
@mike
toDataURL比原始二进制文件更慢/更大。
标签: javascript java image-processing imgscalr