英文:
Creating QR Code as Base64 String using Spring Boot
问题
我正在使用 Spring Boot 创建一个微服务,其中涉及文件处理。我的任务是将 QR 码写入图像文件,并对其进行 base64 编码以便在网络上传输。因为我需要先将数据写入图像文件,然后读取并进行 base64 编码,所以我需要首先创建图像文件,然后再将数据写入它。
是创建一个临时文件夹并在其中保存文件?还是在根目录下创建一个文件夹并保存文件?抑或是使用 java.io.tmpdir ....
注意:一旦我编码后,就不再需要这个文件。而且有很多用户将通过 REST API 使用此服务。
我想知道最佳做法是什么。
英文:
I am creating a microservice using spring boot where in i have a file handling.
My task is to write the QR code to image file and base64 encode to transfer over network.
Because I need to write to an image file and then read and then base64 encode it , I need to first create the image file and then write to it.
Creating a temperory folder and keep the file ?, create a folder in root directory and keep the file? or use the java.io.tmpdir ....
Note: I have no use of this file once I encode it. Also there are lot of user to whom we will be exposing this service as rest api.
I want to know what is the best way to do this.
答案1
得分: 2
如果您正在使用 https://github.com/zxing/zxing 库,即
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.1</version>
</dependency>
那么类似以下的代码将会有效。
@RestController
public class TestController {
@GetMapping(value = "/test")
public QrInfo getQrInfo() throws Exception {
String url = "https://news.bbc.co.uk";
int imageSize = 200;
BitMatrix matrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE,
imageSize, imageSize);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(matrix, "png", bos);
String image = Base64.getEncoder().encodeToString(bos.toByteArray()); // base64 encode
// return QrInfo
QrInfo qrInfo = new QrInfo();
qrInfo.setUrl(url);
qrInfo.setImage(image);
return qrInfo;
}
}
@Data // lombok for brevity
class QrInfo {
private String url;
private String image;
}
注意:这个方法不会写入任何文件,而是都在内存中使用
ByteArrayOutputStream
进行操作。
如果您访问这个端点,您将会看到如下内容: -
{
"url": "https://news.bbc.co.uk",
"image": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAQAAAACFI5MzAAABGUlEQVR42u2YSw7DIAxEzYpjcFM+N+UYrErtMUkjpd2WWQQlyudtLI89JpH5a8lDHvJnUkVXmkMPKcMeAg1peo70inrpRbm/ISFDwkhNX4NUSWxEo26WVFKisgc2ArWncSO3OthJvEs0nTju/bOT+NJKzJK++c5OovJWRIob2AwNsf6YXWJ3eFGbgXS4skgEGafaDGSifVONS/ZCQ/Q2YI5l8BdSS0ImwtTezehjiM9C3FG8fbVdykft/URTeEY918hlIZZFC9Yq0Rw6ns63nyxXtkTCYK6VuJv4NKvmMdgFMBHfBbRjb8JFxgoWW04RPmKfEaY2pgcZcT/OsL3GQ5baFrUN23iZZrvJ6pKjDJFXFvL8P3jIfvIGvNX7jsCaJvEAAAAASUVORK5CYII="
}
如果您将这个 Base64 码粘贴到例如 https://codebeautify.org/base64-to-image-converter 并且用手机摄像头对准,您将会看到这个 URL。
如果您想要在渲染时展示这个内容,方法很简单,例如在 React 中(任何 JavaScript 方法类似)。
<img src={`data:image/png;base64,${image}`} />
我喜欢这个方法,因为如果您需要生成双因素认证码(2FA),您可以同时传递随机密钥和 QR 码,这对于备份很有用,以备用户无法访问移动设备的情况。
英文:
If you are using the https://github.com/zxing/zxing library i.e.
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.1</version>
</dependency>
Then something like the following will work.
@RestController
public class TestController {
@GetMapping(value = "/test")
public QrInfo getQrInfo() throws Exception {
String url = "https://news.bbc.co.uk";
int imageSize = 200;
BitMatrix matrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE,
imageSize, imageSize);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(matrix, "png", bos);
String image = Base64.getEncoder().encodeToString(bos.toByteArray()); // base64 encode
// return QrInfo
QrInfo qrInfo = new QrInfo();
qrInfo.setUrl(url);
qrInfo.setImage(image);
return qrInfo;
}
}
@Data // lombok for brevity
class QrInfo {
private String url;
private String image;
}
> NOTE: This approach doesn't write any files but does it all in-memory using a ByteArrayOutputStream
.
If you hit this endpoint you'll see the following: -
{
"url": "https://news.bbc.co.uk",
"image": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAQAAAACFI5MzAAABGUlEQVR42u2YSw7DIAxEzYpjcFM+N+UYrErtMUkjpd2WWQQlyudtLI89JpH5a8lDHvJnUkVXmkMPKcMeAg1peo70inrpRbm/ISFDwkhNX4NUSWxEo26WVFKisgc2ArWncSO3OthJvEs0nTju/bOT+NJKzJK++c5OovJWRIob2AwNsf6YXWJ3eFGbgXS4skgEGafaDGSifVONS/ZCQ/Q2YI5l8BdSS0ImwtTezehjiM9C3FG8fbVdykft/URTeEY918hlIZZFC9Yq0Rw6ns63nyxXtkTCYK6VuJv4NKvmMdgFMBHfBbRjb8JFxgoWW04RPmKfEaY2pgcZcT/OsL3GQ5baFrUN23iZZrvJ6pKjDJFXFvL8P3jIfvIGvNX7jsCaJvEAAAAASUVORK5CYII="
}
If you paste the Base64 into e.g https://codebeautify.org/base64-to-image-converter and point camera from your phone you will see the URL.
If you rendering this out it is easy i.e. in React (any JavaScript approach will be similar).
<img src={`data:image/png;base64,${image}`} />
I like this approach as if you are e.g. generate 2FA codes you can pass down both the random secret and the QR code - useful to have both as a backup if the user doesn't have access to a mobile device.
答案2
得分: 0
你可以在你的文件系统中的指定文件夹里轻松地执行此操作,一旦传输完成,你可以删除该文件。但是由于这个操作是通过 REST API 暴露的,所以并发和文件冲突可能是一个问题。为了避免这种情况,你可以为每个文件名赋予唯一的值,这样相同文件名的冲突就可以避免了。
一个方法是使用 UUID 来为文件名命名并将文件存储为该名称在文件系统中。这将确保不会发生冲突。
String fileName = UUID.randomUUID().toString();
英文:
You can do this in a designated folder in your file-system easily and once you are done with the transfer, you can remove the file. But since, this operation is exposed over a rest api, concurrency and file collision can be an issue. To avoid that you can give unique to every file-name, that way same file-name collision can be avoided.
One approach could be to UUID for writing the file-name and storing the file with this name in the file-system. It will ensure collision doesn't occur.
String fileName = UUID.randomUUID().toString();
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论