Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vehicle-quality-review
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
王飞
vehicle-quality-review
Commits
bb64e0e4
Commit
bb64e0e4
authored
Jul 11, 2024
by
wdy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
车型试验原始记录附件下载
parent
97ed5b01
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
279 additions
and
39 deletions
+279
-39
TestRecordsMapper.java
...iew/src/main/java/com/ruoyi/mapper/TestRecordsMapper.java
+7
-0
PdfTemplateManagementService.java
.../java/com/ruoyi/service/PdfTemplateManagementService.java
+9
-0
TestRecordsService.java
...w/src/main/java/com/ruoyi/service/TestRecordsService.java
+7
-0
PdfTemplateManagementServiceImpl.java
.../ruoyi/service/impl/PdfTemplateManagementServiceImpl.java
+105
-0
TestRecordsServiceImpl.java
...n/java/com/ruoyi/service/impl/TestRecordsServiceImpl.java
+10
-0
PdfTemplateManagementController.java
...n/java/com/ruoyi/web/PdfTemplateManagementController.java
+27
-0
FileRequest.java
...view/src/main/java/com/ruoyi/web/request/FileRequest.java
+13
-0
TestRecordsMapper.xml
...ty-review/src/main/resources/mapper/TestRecordsMapper.xml
+5
-0
TestDownload.java
ruoyi-admin/src/test/java/com/ruoyi/TestDownload.java
+96
-39
No files found.
quality-review/src/main/java/com/ruoyi/mapper/TestRecordsMapper.java
View file @
bb64e0e4
...
...
@@ -20,4 +20,11 @@ public interface TestRecordsMapper extends BaseMapper<TestRecords> {
* @return
*/
List
<
TestRecords
>
selectListByGeneralTaskId
(
@Param
(
"id"
)
Long
id
);
/**
* 根据任务id获取用例
* @param taskId
* @return
*/
List
<
TestRecords
>
selectListByTaskId
(
Long
taskId
);
}
quality-review/src/main/java/com/ruoyi/service/PdfTemplateManagementService.java
View file @
bb64e0e4
package
com
.
ruoyi
.
service
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
/**
* PDF模板管理Service接口
* @author gxk
...
...
@@ -31,4 +34,10 @@ public interface PdfTemplateManagementService {
*/
String
generateOriginalRecord
(
Long
taskId
)
throws
Exception
;
/**
* 下载附件
* @param taskId
* @return
*/
void
createZipStream
(
Long
taskId
)
throws
IOException
;
}
quality-review/src/main/java/com/ruoyi/service/TestRecordsService.java
View file @
bb64e0e4
...
...
@@ -26,4 +26,11 @@ public interface TestRecordsService extends IService<TestRecords> {
* @param taskId
*/
void
singleSendPost
(
String
id
,
Long
taskId
);
/**
* 根据任务id获取用例
* @param taskId
* @return
*/
List
<
TestRecords
>
selectListByTaskId
(
Long
taskId
);
}
quality-review/src/main/java/com/ruoyi/service/impl/PdfTemplateManagementServiceImpl.java
View file @
bb64e0e4
package
com
.
ruoyi
.
service
.
impl
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.io.IoUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.http.HttpResponse
;
import
cn.hutool.http.HttpUtil
;
import
com.itextpdf.text.*
;
import
com.itextpdf.text.Font
;
import
com.itextpdf.text.Image
;
...
...
@@ -36,11 +39,13 @@ import com.ruoyi.mapper.TaskMapper;
import
com.ruoyi.mapper.TestRecordsMapper
;
import
com.ruoyi.service.PdfTemplateManagementService
;
import
com.ruoyi.service.ReviewEnterpriseArchiveService
;
import
com.ruoyi.service.TestRecordsService
;
import
com.ruoyi.system.mapper.SysDictDataMapper
;
import
io.minio.MinioClient
;
import
io.minio.ObjectWriteArgs
;
import
io.minio.PutObjectArgs
;
import
lombok.SneakyThrows
;
import
org.apache.commons.io.IOUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
...
...
@@ -48,10 +53,14 @@ import org.springframework.transaction.annotation.Transactional;
import
java.io.*
;
import
java.lang.reflect.Field
;
import
java.net.URL
;
import
java.net.URLDecoder
;
import
java.nio.charset.StandardCharsets
;
import
java.util.*
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipOutputStream
;
/**
* PDF模板管理Service业务层处理
...
...
@@ -88,6 +97,9 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
@Autowired
private
TestRecordsMapper
testRecordsMapper
;
@Autowired
private
TestRecordsService
testRecordsService
;
/**
* 检验报告PDF下载
*
...
...
@@ -310,6 +322,99 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
return
uploadMinio
(
arrayOutputStream
,
"车辆试验原始记录-"
+
getReportName
());
}
/**
* 车辆试验原始记录附件下载
* @param taskId
* @throws IOException
*/
@Override
public
void
createZipStream
(
Long
taskId
)
throws
IOException
{
// 用于存储已经添加的文件名
Set
<
String
>
addedFiles
=
new
HashSet
<>();
// 压缩包的名称和路径
String
zipFilePath
=
"D:\\downloaded_files.zip"
;
// 创建ZIP输出流
// FileOutputStream fos = new FileOutputStream(zipFilePath);
// ZipOutputStream zos = new ZipOutputStream(fos);
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
zipFilePath
);
ZipOutputStream
zos
=
new
ZipOutputStream
(
fos
))
{
List
<
TestRecords
>
list
=
testRecordsService
.
selectListByTaskId
(
taskId
);
// 转换列表中每个 TestRecords 对象的 attachmentId 字段为字符串数组
List
<
String
[]>
convertedList
=
list
.
stream
()
.
filter
(
testRecord
->
{
String
attachmentId
=
testRecord
.
getAttachmentId
();
return
attachmentId
!=
null
;
})
.
map
(
testRecord
->
testRecord
.
getAttachmentId
().
split
(
"、"
))
.
collect
(
Collectors
.
toList
());
// 遍历convertedList中的每个数组
for
(
String
[]
attachments
:
convertedList
)
{
// 遍历数组中的每个元素
for
(
String
attachmentId
:
attachments
)
{
HttpResponse
response
=
HttpUtil
.
createPost
(
"https://10.12.48.78:8090/api/project/download/"
+
attachmentId
)
.
execute
();
if
(
response
.
isOk
())
{
// 从响应头中获取文件名,这里Content-Disposition头包含文件名
String
contentDisposition
=
response
.
header
(
"Content-Disposition"
);
String
fileName
=
parseAndDecodeFilename
(
contentDisposition
);
if
(
StrUtil
.
isNotBlank
(
fileName
)
&&
!
addedFiles
.
contains
(
fileName
))
{
addedFiles
.
add
(
fileName
);
// 添加文件名到集合中
// 创建ZIP条目并写入到ZIP输出流
ZipEntry
zipEntry
=
new
ZipEntry
(
fileName
);
zos
.
putNextEntry
(
zipEntry
);
// 直接从HTTP响应中读取字节并写入到ZIP输出流
IOUtils
.
copy
(
response
.
bodyStream
(),
zos
);
// 完成条目写入
zos
.
closeEntry
();
// 关闭输出流
// IoUtil.close(zos);
// IoUtil.close(fos);
System
.
out
.
println
(
"文件已添加到压缩包:"
+
zipFilePath
);
}
else
{
System
.
err
.
println
(
"无法从响应头中提取文件名"
);
}
}
else
{
System
.
err
.
println
(
"下载失败,状态码:"
+
response
.
getStatus
());
}
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
/**
* 解码文件名称
* @param contentDisposition
* @return
* @throws UnsupportedEncodingException
*/
private
String
parseAndDecodeFilename
(
String
contentDisposition
)
throws
UnsupportedEncodingException
{
String
[]
parts
=
contentDisposition
.
split
(
"; "
);
for
(
String
part
:
parts
)
{
if
(
part
.
startsWith
(
"filename*"
))
{
// 分割出编码后的文件名,忽略前缀如 utf8''
int
start
=
part
.
indexOf
(
"''"
)
+
2
;
String
encodedFileName
=
part
.
substring
(
start
).
trim
();
// 解码文件名
return
URLDecoder
.
decode
(
encodedFileName
,
String
.
valueOf
(
StandardCharsets
.
UTF_8
));
}
}
return
null
;
// 如果没有找到filename*则返回null
}
/**
* 创建临时文档
* @param sample 样品信息
...
...
quality-review/src/main/java/com/ruoyi/service/impl/TestRecordsServiceImpl.java
View file @
bb64e0e4
...
...
@@ -260,6 +260,16 @@ public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestR
}
}
/**
* 根据任务id获取用例
* @param taskId
* @return
*/
@Override
public
List
<
TestRecords
>
selectListByTaskId
(
Long
taskId
)
{
return
testRecordsMapper
.
selectListByTaskId
(
taskId
);
}
public
static
String
convertMarkdownToHtml
(
String
markdownContent
)
{
// 创建 Markdown 解析器
Parser
parser
=
Parser
.
builder
().
build
();
...
...
quality-review/src/main/java/com/ruoyi/web/PdfTemplateManagementController.java
View file @
bb64e0e4
package
com
.
ruoyi
.
web
;
import
cn.hutool.core.io.IoUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper
;
...
...
@@ -8,13 +9,22 @@ import com.ruoyi.common.core.domain.R;
import
com.ruoyi.domain.Task
;
import
com.ruoyi.service.PdfTemplateManagementService
;
import
com.ruoyi.service.TaskService
;
import
com.ruoyi.web.request.FileRequest
;
import
com.ruoyi.web.request.PdfFileRequest
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.*
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipOutputStream
;
/**
* @author gxk
*/
...
...
@@ -150,4 +160,21 @@ public class PdfTemplateManagementController {
}
return
R
.
ok
(
url
);
}
@Anonymous
@ApiOperation
(
"下载附件"
)
@PostMapping
(
"/downloadFile"
)
public
void
downloadFile
(
@Validated
@RequestBody
FileRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
String
zipFilePath
=
"D:\\downloaded_files.zip"
;
pdfTemplateManagementService
.
createZipStream
(
request
.
getTaskId
());
// 设置响应头以便浏览器识别为下载
response
.
setHeader
(
"Content-Disposition"
,
"attachment; filename=downloaded_files.zip"
);
response
.
setContentType
(
"application/zip"
);
// 将压缩文件流发送到客户端
try
(
FileInputStream
fis
=
new
FileInputStream
(
new
File
(
zipFilePath
)))
{
IoUtil
.
copy
(
fis
,
response
.
getOutputStream
());
}
}
}
quality-review/src/main/java/com/ruoyi/web/request/FileRequest.java
0 → 100644
View file @
bb64e0e4
package
com
.
ruoyi
.
web
.
request
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
@ApiModel
(
value
=
"FileRequest"
,
description
=
"下载附件"
)
@Data
public
class
FileRequest
{
@ApiModelProperty
(
"任务id"
)
Long
taskId
;
}
quality-review/src/main/resources/mapper/TestRecordsMapper.xml
View file @
bb64e0e4
...
...
@@ -52,6 +52,11 @@
where
t.id = #{id}
</select>
<select
id=
"selectListByTaskId"
resultType=
"com.ruoyi.domain.TestRecords"
>
SELECT id, project_id, task_id, usecase, usecase_no, usecase_id, test_time, description, risk_level, test_method, test_result, remediation, test_details, attachment_id, attachment_name
FROM t_test_records
WHERE task_id = #{taskId}
</select>
</mapper>
ruoyi-admin/src/test/java/com/ruoyi/TestDownload.java
View file @
bb64e0e4
...
...
@@ -6,72 +6,129 @@ import cn.hutool.core.util.StrUtil;
import
cn.hutool.http.HttpResponse
;
import
cn.hutool.http.HttpUtil
;
import
cn.hutool.core.util.ZipUtil
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.ruoyi.domain.TestRecords
;
import
com.ruoyi.service.TestRecordsService
;
import
org.apache.commons.io.IOUtils
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLDecoder
;
import
java.nio.charset.StandardCharsets
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.stream.Collectors
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipOutputStream
;
@SpringBootTest
public
class
TestDownload
{
@Autowired
private
TestRecordsService
testRecordsService
;
@Test
public
void
Test
()
{
try
{
// 压缩包的名称和路径
String
zipFilePath
=
"downloaded_files.zip"
;
public
void
Test
()
throws
FileNotFoundException
{
Set
<
String
>
addedFiles
=
new
HashSet
<>();
// 用于存储已经添加的文件名
// 压缩包的名称和路径
String
zipFilePath
=
"D:\\downloaded_files.zip"
;
// 创建ZIP输出流
// FileOutputStream fos = new FileOutputStream(zipFilePath);
// ZipOutputStream zos = new ZipOutputStream(fos);
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
zipFilePath
);
ZipOutputStream
zos
=
new
ZipOutputStream
(
fos
))
{
Long
taskId
=
1808391769025445890L
;
List
<
TestRecords
>
list
=
testRecordsService
.
selectListByTaskId
(
taskId
);
list
.
forEach
(
testRecord
->
{
System
.
out
.
println
(
"testRecord = "
+
testRecord
);
});
// 转换列表中每个 TestRecords 对象的 attachmentId 字段为字符串数组
List
<
String
[]>
convertedList
=
list
.
stream
()
.
filter
(
testRecord
->
{
String
attachmentId
=
testRecord
.
getAttachmentId
();
return
attachmentId
!=
null
;
})
.
map
(
testRecord
->
testRecord
.
getAttachmentId
().
split
(
"、"
))
.
collect
(
Collectors
.
toList
());
HttpResponse
response
=
HttpUtil
.
createPost
(
"https://10.12.48.78:8090/api/project/download/fd40de37-9c57-4597-8f74-d0754dfa17b2"
)
.
execute
();
convertedList
.
forEach
(
testRecord
->
{
System
.
out
.
println
(
"convertedList = "
+
testRecord
);
});
// 遍历convertedList中的每个数组
for
(
String
[]
attachments
:
convertedList
)
{
// 遍历数组中的每个元素
for
(
String
attachmentId
:
attachments
)
{
HttpResponse
response
=
HttpUtil
.
createPost
(
"https://10.12.48.78:8090/api/project/download/"
+
attachmentId
)
.
execute
();
if
(
response
.
isOk
())
{
// 从响应头中获取文件名,这里假设Content-Disposition头包含文件名
String
contentDisposition
=
response
.
header
(
"Content-Disposition"
);
String
fileName
=
extractFileNameFromContentDisposition
(
contentDisposition
);
if
(
response
.
isOk
())
{
System
.
out
.
println
(
"response = "
+
response
);
if
(
StrUtil
.
isNotBlank
(
fileName
))
{
// 从响应头中获取文件名,这里Content-Disposition头包含文件名
String
contentDisposition
=
response
.
header
(
"Content-Disposition"
);
String
fileName
=
parseAndDecodeFilename
(
contentDisposition
);
// 保存下载的文件到临时位置
String
tempFilePath
=
"temp_"
+
fileName
;
FileUtil
.
writeBytes
(
IoUtil
.
readBytes
(
response
.
bodyStream
()),
FileUtil
.
file
(
tempFilePath
));
if
(
StrUtil
.
isNotBlank
(
fileName
)
&&
!
addedFiles
.
contains
(
fileName
))
{
addedFiles
.
add
(
fileName
);
// 添加文件名到集合中
System
.
out
.
println
(
"文件下载成功:"
+
fileName
);
// 创建ZIP条目并写入到ZIP输出流
ZipEntry
zipEntry
=
new
ZipEntry
(
fileName
);
zos
.
putNextEntry
(
zipEntry
);
// 将临时文件添加到压缩包中
// ZipUtil.addFile(zipFilePath, tempFilePath
);
// 直接从HTTP响应中读取字节并写入到ZIP输出流
IOUtils
.
copy
(
response
.
bodyStream
(),
zos
);
System
.
out
.
println
(
"文件已添加到压缩包:"
+
zipFilePath
);
// 完成条目写入
zos
.
closeEntry
();
// 删除临时文件
FileUtil
.
del
(
tempFilePath
);
}
else
{
System
.
err
.
println
(
"无法从响应头中提取文件名"
);
// 关闭输出流
// IoUtil.close(zos);
// IoUtil.close(fos);
System
.
out
.
println
(
"文件已添加到压缩包:"
+
zipFilePath
);
}
else
{
System
.
err
.
println
(
"无法从响应头中提取文件名"
);
}
}
else
{
System
.
err
.
println
(
"下载失败,状态码:"
+
response
.
getStatus
());
}
}
}
else
{
System
.
err
.
println
(
"下载失败,状态码:"
+
response
.
getStatus
());
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
/**
* 从Content-Disposition头中提取文件名。
* 注意:这是一个简化的示例,真实场景可能需要更复杂的解析逻辑。
*
* @param contentDisposition Content-Disposition头的值
* @return 提取的文件名,如果未找到则返回空字符串
* 解码文件名称
* @param contentDisposition
* @return
* @throws UnsupportedEncodingException
*/
private
static
String
extractFileNameFromContentDisposition
(
String
contentDisposition
)
{
if
(
StrUtil
.
isBlank
(
contentDisposition
))
{
return
""
;
}
String
[]
parts
=
contentDisposition
.
split
(
";"
);
private
static
String
parseAndDecodeFilename
(
String
contentDisposition
)
throws
UnsupportedEncodingException
{
String
[]
parts
=
contentDisposition
.
split
(
"; "
);
for
(
String
part
:
parts
)
{
part
=
part
.
trim
();
if
(
part
.
startsWith
(
"filename="
))
{
return
part
.
substring
(
part
.
indexOf
(
'='
)
+
1
).
replace
(
"\""
,
""
);
if
(
part
.
startsWith
(
"filename*"
))
{
// 分割出编码后的文件名,忽略前缀如 utf8''
int
start
=
part
.
indexOf
(
"''"
)
+
2
;
String
encodedFileName
=
part
.
substring
(
start
).
trim
();
// 解码文件名
return
URLDecoder
.
decode
(
encodedFileName
,
String
.
valueOf
(
StandardCharsets
.
UTF_8
));
}
}
return
""
;
return
null
;
// 如果没有找到filename*则返回null
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment