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
cdb52718
Commit
cdb52718
authored
Jul 11, 2024
by
wdy
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wangdingyi' into 'dev'
车型试验原始记录附件下载 See merge request
!408
parents
97ed5b01
bb64e0e4
Changes
9
Show 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 @
cdb52718
...
...
@@ -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 @
cdb52718
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 @
cdb52718
...
...
@@ -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 @
cdb52718
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 @
cdb52718
...
...
@@ -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 @
cdb52718
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 @
cdb52718
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 @
cdb52718
...
...
@@ -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 @
cdb52718
...
...
@@ -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
{
public
void
Test
()
throws
FileNotFoundException
{
Set
<
String
>
addedFiles
=
new
HashSet
<>();
// 用于存储已经添加的文件名
// 压缩包的名称和路径
String
zipFilePath
=
"downloaded_files.zip"
;
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
);
});
HttpResponse
response
=
HttpUtil
.
createPost
(
"https://10.12.48.78:8090/api/project/download/fd40de37-9c57-4597-8f74-d0754dfa17b2"
)
// 转换列表中每个 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
.
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头包含文件名
System
.
out
.
println
(
"response = "
+
response
);
// 从响应头中获取文件名,这里Content-Disposition头包含文件名
String
contentDisposition
=
response
.
header
(
"Content-Disposition"
);
String
fileName
=
extractFileNameFromContentDisposition
(
contentDisposition
);
String
fileName
=
parseAndDecodeFilename
(
contentDisposition
);
if
(
StrUtil
.
isNotBlank
(
fileName
))
{
if
(
StrUtil
.
isNotBlank
(
fileName
)
&&
!
addedFiles
.
contains
(
fileName
))
{
addedFiles
.
add
(
fileName
);
// 添加文件名到集合中
// 保存下载的文件到临时位置
String
tempFilePath
=
"temp_"
+
fileName
;
FileUtil
.
writeBytes
(
IoUtil
.
readBytes
(
response
.
bodyStream
()),
FileUtil
.
file
(
tempFilePath
)
);
// 创建ZIP条目并写入到ZIP输出流
ZipEntry
zipEntry
=
new
ZipEntry
(
fileName
)
;
zos
.
putNextEntry
(
zipEntry
);
System
.
out
.
println
(
"文件下载成功:"
+
fileName
);
// 直接从HTTP响应中读取字节并写入到ZIP输出流
IOUtils
.
copy
(
response
.
bodyStream
(),
zos
);
// 将临时文件添加到压缩包中
// ZipUtil.addFile(zipFilePath, tempFilePath);
// 完成条目写入
zos
.
closeEntry
();
// 关闭输出流
// IoUtil.close(zos);
// IoUtil.close(fos);
System
.
out
.
println
(
"文件已添加到压缩包:"
+
zipFilePath
);
// 删除临时文件
FileUtil
.
del
(
tempFilePath
);
}
else
{
System
.
err
.
println
(
"无法从响应头中提取文件名"
);
}
}
else
{
System
.
err
.
println
(
"下载失败,状态码:"
+
response
.
getStatus
());
}
}
}
}
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