Zay*_*Lim 8 java sql-server spring download spring-boot
我正在使用 Spring Boot、JSP 和 MSSQL 上传和下载文件。我可以运行上传和下载功能,但从数据库下载的文件已损坏。谁能帮我这个?
这是我的春季版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.3-SNAPSHOT</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
Run Code Online (Sandbox Code Playgroud)
我的控制器
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public ResponseEntity < Object > upload(@RequestPart(required = false) MultipartFile file) throws IOException {
try {
if (file != null) {
tmDAO.storeFile(file, tm);
}
return new ResponseEntity < Object > ("success", HttpStatus.OK);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@RequestMapping("/downloadFile/{id}")
public String downloadFile(@PathVariable("id") String id,
HttpServletResponse res) throws IOException {
FileModel fm = tmDAO.getFile(id);
try {
File file = new File(fm.getName());
FileOutputStream fos = new FileOutputStream(file);
res.setContentLength(fm.getData().length);
res.setHeader("Content-Disposition", "attachment; filename=" + fm.getName());
fos.write(fm.getData(), 0, fm.getData().length);
fos.flush();
fos.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return "string";
}
Run Code Online (Sandbox Code Playgroud)
服务
@Override
public FileModel storeFile(MultipartFile file, TeachingMaterial tm) throws IOException {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
FileModel fileModel = new FileModel(UUID.randomUUID().toString(), tm.getContributor(), fileName,
file.getContentType(), file.getBytes(), tm.getClassName(), tm.getSubjectName(), tm.getSlots());
return fileRepo.save(fileModel);
}
@Override
public FileModel getFile(String id) throws IOException {
Optional < FileModel > fm = fileRepo.findById(id);
if (fm.isPresent()) {
return fm.get();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
文件模型.java
@Entity
@Table(name = "FILES")
public class FileModel {
@Id
private String id;
private String contributor;
private String name;
private String type;
@Lob
private byte[] data;
private String className;
private String subjectName;
private String slots;
public FileModel() {
super();
}
public FileModel(String id, String contributor, String name, String type, byte[] data, String className,
String subjectName, String slots) {
super();
this.id = id;
this.contributor = contributor;
this.name = name;
this.type = type;
this.data = data;
this.className = className;
this.subjectName = subjectName;
this.slots = slots;
}
**I skips the getters and setters for simplication**
}
Run Code Online (Sandbox Code Playgroud)
在MSSQL中记录
下载txt文件后我得到了什么
原始数据应该是
测试123
ABC
有人可以帮我解决这个问题吗?
我认为问题可能与您执行文件下载的方式有关:
@RequestMapping("/downloadFile/{id}")
public String downloadFile(@PathVariable("id") String id,
HttpServletResponse res) throws IOException {
FileModel fm = tmDAO.getFile(id);
try {
File file = new File(fm.getName());
FileOutputStream fos = new FileOutputStream(file);
res.setContentLength(fm.getData().length);
res.setHeader("Content-Disposition", "attachment; filename=" + fm.getName());
fos.write(fm.getData(), 0, fm.getData().length);
fos.flush();
fos.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return "string";
}
Run Code Online (Sandbox Code Playgroud)
请注意,在您的代码中,您正在将获得的FileModel数据写入 a FileOutputStream,但您应该将该数据写入HttpServletResponse底层OutputStream。请考虑对您的代码进行以下修改:
@RequestMapping("/downloadFile/{id}")
public void downloadFile(
@PathVariable("id") String id,
HttpServletResponse res
) throws IOException {
// Define an auxiliary InputStream: more on this later
InputStream in = null;
// Define a reference to the response OutputStream. We will initialize
// it later
OutputStream out = null;
try {
FileModel fm = tmDAO.getFile(id);
byte[] data = fm.getData();
// initialize the response content-type (perhaps with type?)
// and additional headers
res.setContentType("application/octet-stream");
res.setContentLength(data.length);
res.setHeader("Content-Disposition",
"attachment; filename=" + fm.getName());
// write data to output
// This variable ideally should be defined as a constant
int BUFFER_SIZE = 4096;
byte[] buffer = new byte[BUFFER_SIZE];
in = new ByteArrayInputStream(data);
out = res.getOutputStream();
while(data.read(buffer, 0, BUFFER_SIZE) != -1) {
out.write(buffer, 0, BUFFER_SIZE);
}
out.flush();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
// cleanup
if (in != null) {
try {
in.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
// there is no need to return anything
}
Run Code Online (Sandbox Code Playgroud)
如果您愿意,可以使用Apache Commons IO 项目中方便的IOUtils类大大简化此过程:
@RequestMapping("/downloadFile/{id}")
public void downloadFile(
@PathVariable("id") String id,
HttpServletResponse res
) throws IOException {
// Define a reference to the response OutputStream. We will initialize
// it later
OutputStream out = null;
try {
FileModel fm = tmDAO.getFile(id);
byte[] data = fm.getData();
// initialize the response content-type (perhaps with type?)
// and additional headers
res.setContentType("application/octet-stream");
res.setContentLength(data.length);
res.setHeader("Content-Disposition",
"attachment; filename=" + fm.getName());
// write data to output
out = res.getOutputStream();
// As suggested by @Olivier in this comments, we can
// get rid of the ByteArrayInputStream and use data directly
IOUtils.copy(data, out);
out.flush();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
// cleanup
IOUtils.closeQuietly(out);
}
// there is no need to return anything
}
Run Code Online (Sandbox Code Playgroud)
Spring 提供了额外的方法来处理写入byte[]线路,但您的解决方案是一种简单且非常好的解决方案。
| 归档时间: |
|
| 查看次数: |
800 次 |
| 最近记录: |