如何解决为什么下面的文件生成方法会在同时请求此端点时返回 FileNotFoundException?
我编写了一个端点来返回一个包含多个 qr 的 zip,其中包含基于我的数据库中的详细信息的值。当我通过向该端点发出多个请求来进行负载测试时,它抛出 FileNotFoundException。但如果请求是在特定时间间隔内发出的,则不会发生这种情况。
@GetMapping(value = ["/{sysId}/code"],produces = ["application/zip"])
fun generateQrCode1(@PathVariable sysId: Int): ResponseEntity<InputStreamResource> {
val sysDetails = sysService.getById(sysId)
val productDetails = productService.getProductByProductId(sysDetails.productId)
val zipName = sysDetails.productId.toString() + ".zip"
FileOutputStream(zipName).use { fileOutputStream ->
ZipOutputStream(fileOutputStream).use { zipOutputStream ->
for (i in 1..sysDetails.length) {
val u = "http://" + "$domain/" + "?sysId=${sysId}&pid=$i"
val x = generateQRCodeWithText(u,350,300,arrayOf("QR CODE TEST"))
val byteArrayOutputStream = ByteArrayOutputStream()
byteArrayOutputStream.write(x!!)
val zipEntry = ZipEntry(
"${
productDetails.name
}-${sysId}-$i.jpg"
)
zipOutputStream.putNextEntry(zipEntry)
byteArrayOutputStream.writeto(zipOutputStream)
}
}
}
try {
return ResponseEntity
.ok()
.header("Content-disposition","attachment; filename=\"$zipName")
.body(InputStreamResource(FileInputStream(zipName)))
} finally {
java.nio.file.Files.deleteIfExists(Paths.get(zipName))
}
fun generateQRCodeWithText(data: String?,width: Int?,height: Int,text: Array<String?>): ByteArray? {
return try {
val qrCodeWriter = QRCodeWriter()
val bitMatrix = qrCodeWriter.encode(data,BarcodeFormat.QR_CODE,width!!,height)
val pngOutputStream = ByteArrayOutputStream()
MatrixToImageWriter.writetoStream(bitMatrix,"PNG",pngOutputStream)
var pngData = pngOutputStream.toByteArray()
if (text.size > 0) {
val totalTextLinetoadd = text.size
val `in`: InputStream = ByteArrayInputStream(pngData)
val image: BufferedImage = ImageIO.read(`in`)
val outputimage =
BufferedImage(image.width,image.height + 25 * totalTextLinetoadd,BufferedImage.TYPE_INT_ARGB)
val g: Graphics = outputimage.graphics
val g2d = g as Graphics2D
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setColor(Color.WHITE)
g.fillRect(0,outputimage.width,outputimage.height)
g.drawImage(image,image.width,image.height,null)
g.setFont(Font("Arial Black",Font.BOLD,20))
val textColor: Color = Color.BLUE
g.setColor(textColor)
val fm: FontMetrics = g.getFontMetrics()
var startingYposition = height + 5
for (displayText in text) {
g.drawString(
displayText,outputimage.width / 2 - fm.stringWidth(displayText) / 2,startingYposition
)
startingYposition += 20
}
val baos = ByteArrayOutputStream()
ImageIO.write(outputimage,baos)
baos.flush()
pngData = baos.toByteArray()
baos.close()
}
pngData
} catch (ex: WriterException) {
throw ex
} catch (ex: IOException) {
throw ex
}
}
多个请求同时出错:
java.io.FileNotFoundException: 2889.zip (No such file or directory)
at java.io.FileInputStream.open0(Native Method) ~[?:1.8.0_292]
at java.io.FileInputStream.open(FileInputStream.java:195) ~[?:1.8.0_292]
at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[?:1.8.0_292]
at java.io.FileInputStream.<init>(FileInputStream.java:93) ~[?:1.8.0_292]
at com.mangoChain.qrApi.QrApi.generateQrCode1(QrApi.kt:136) ~[classes!/:?]
解决方法
您应该确保您的本地文件名 (zipName
) 是唯一的,否则多个线程可能会删除彼此的文件。
您在评论中提到 productId
可能会发生冲突,因此您可以基于 sysId
而不是(或除了)productId
来命名您的文件。例如:
val zipName = "$sysId-${sysDetails.productId}.zip"
请注意,您只需要使本地文件名唯一 (zipName
),但您仍然可以在 Content-Disposition
标题中保留用户可见的文件名:
return ResponseEntity
.ok()
.header("Content-Disposition","attachment; filename=\"${sysDetails.productId}.zip\"")
.body(InputStreamResource(FileInputStream(zipName)))
作为旁注,您可能应该使用临时文件夹而不仅仅是普通的文件名,因为目前这些文件是在当前工作目录中创建的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。