首先对struts.xml进行配置,如下:
<action name="result_*" class="resultAction" method="{1}">
<result name="resultTable" type="stream">
<param name="inputName">inputStream</param>
<param name="contentType">application/octet-stream</param>
<param name="contentDisposition">filename=${name}</param>
</result>
</action>
其中result的类型需设为stream,其他字段属性见下:
1.contentType:同文件上传的一样,为下载文件的格式,上例中表示所有类型;
2.contentLength:要下载的文件的文件大小;
3.contentDisposition:有两个属性,inlie和attachment(默认是inline(内联),例如下载文件是文本类型的,就直接在网页上打开,不能直接打开的才会打开下载框自己选择,要想弹出下载框可用附件的形式attachment),可知道下载文件的文件名称;
4.bufferSize:下载缓冲区的大小,默认1024;
5.inputName:定义输入流的名字,默认inputStream。
action内代码:
protected InputStream inputStream;
protected String name;
public String getName() {
return name;
}
public InputStream getInputStream() {
return inputStream;
}
public String export(){
String time = DateFormat.dateToRowkey(new Date());//将当前时间变为如下格式:yyyymmddhhmmss
String outPath = ServletActionContext.getServletContext().getRealPath("file/export/")+"test"+time+model.getType();
outPath = resultService.export(outPath, model.getType(), model.getParam());//type:导出文件后缀(例.xlsx,.docx,.pdf,.jpg),param是文件内容,service中的方法是生成文件并返回文件路径(当生成文件格式为.jpg时,有时会是多张图片,就需要对多张图片进行压缩)
if(outPath.endsWith(".zip")){
name = "test"+time+".zip";
inputStream = ServletActionContext.getServletContext().getResourceAsStream("file/export/"+"test"+time+".zip");
}else{
name = "test"+time+model.getType();
inputStream = ServletActionContext.getServletContext().getResourceAsStream("file/export/"+"test"+time+model.getType());
}
}
service中代码片段:
else if(type.equals(".jpg")){
Table table = pdfWrite.getContribute(source, receiver, val);
pdfWrite.exportPDF(table, outPath.replaceAll(".jpg", ".pdf"));//先生成PDF文件 再转为jpg
List<String> files = pdfToImage.pdftoIamge(4.0f, outPath.replaceAll(".jpg", ".pdf"), outPath.replaceAll(".jpg", ""));
if(files.size()>0){
File[] fs = new File[files.size()];
for(int i=0;i<fs.length;i++){
fs[i] = new File(files.get(i));
}
ZipFileUtil.compressFiles2Zip(fs, outPath.replaceAll(".jpg", ".zip"));//对jpg文件进行压缩
return outPath.replaceAll(".jpg", ".zip");
}
}
pdf转jpg代码:
/**
* 生成pdf的缩略图
* @param zoom 缩略图显示倍数,1表示不缩放,0.5表示缩小到50%
* @param inputFile 需要生成缩略图的书籍的完整路径
* @param outputFile 生成缩略图的放置路径
*/
public List<String> pdftoIamge(float zoom,String inputFile, String outputFile) {
List<String> list = null;
Document document = null;
try {
list = new ArrayList(0);
document = new Document();
document.setFile(inputFile);
float rotation = 0;
int maxPages = document.getPageTree().getNumberOfPages();
for (int i = 0; i < maxPages; i++) {
BufferedImage bfimage = (BufferedImage) document.getPageImage(i,GraphicsRenderingHints.SCREEN,Page.BOUNDARY_CROPBOX,rotation,zoom);
//bfimage = setGraphics(bfimage); //水印
RenderedImage rendImage = bfimage;
ImageIO.write(rendImage, "jpg", new File(outputFile+i+".jpg"));
bfimage.flush();
list.add(outputFile+i+".jpg");
}
}catch (Exception e) {
e.printStackTrace();
}
if(document!=null){
document.dispose();
}
return list;
}
文件压缩代码:
/**
* 把文件压缩成zip格式
* @param files 需要压缩的文件
* @param zipFilePath 压缩后的zip文件路径 ,如"D:/test/aa.zip";
*/
public static void compressFiles2Zip(File[] files,String zipFilePath) {
if(files != null && files.length >0) {
if(isEndsWithZip(zipFilePath)) {
ZipArchiveOutputStream zaos = null;
try {
File zipFile = new File(zipFilePath);
zaos = new ZipArchiveOutputStream(zipFile);
//Use Zip64 extensions for all entries where they are required
zaos.setUseZip64(Zip64Mode.AsNeeded);
//将每个文件用ZipArchiveEntry封装
//再用ZipArchiveOutputStream写到压缩文件中
for(File file : files) {
if(file != null) {
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,file.getName());
zaos.putArchiveEntry(zipArchiveEntry);
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[1024 * 5];
int len = -1;
while((len = is.read(buffer)) != -1) {
//把缓冲区的字节写入到ZipArchiveEntry
zaos.write(buffer, 0, len);
}
//Writes all necessary data for this entry.
zaos.closeArchiveEntry();
}catch(Exception e) {
throw new RuntimeException(e);
}finally {
if(is != null)
is.close();
}
}
}
zaos.finish();
}catch(Exception e){
throw new RuntimeException(e);
}finally {
try {
if(zaos != null) {
zaos.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 把zip文件解压到指定的文件夹
* @param zipFilePath zip文件路径, 如 "D:/test/aa.zip"
* @param saveFileDir 解压后的文件存放路径, 如"D:/test/"
*/
public static void decompressZip(String zipFilePath,String saveFileDir) {
if(isEndsWithZip(zipFilePath)) {
File file = new File(zipFilePath);
if(file.exists()) {
InputStream is = null;
//can read Zip archives
ZipArchiveInputStream zais = null;
try {
is = new FileInputStream(file);
zais = new ZipArchiveInputStream(is);
ArchiveEntry archiveEntry = null;
//把zip包中的每个文件读取出来
//然后把文件写到指定的文件夹
while((archiveEntry = zais.getNextEntry()) != null) {
//获取文件名
String entryFileName = archiveEntry.getName();
//构造解压出来的文件存放路径
String entryFilePath = saveFileDir + entryFileName;
byte[] content = new byte[(int) archiveEntry.getSize()];
zais.read(content);
OutputStream os = null;
try {
//把解压出来的文件写到指定路径
File entryFile = new File(entryFilePath);
os = new BufferedOutputStream(new FileOutputStream(entryFile));
os.write(content);
}catch(IOException e) {
throw new IOException(e);
}finally {
if(os != null) {
os.flush();
os.close();
}
}
}
}catch(Exception e) {
throw new RuntimeException(e);
}finally {
try {
if(zais != null) {
zais.close();
}
if(is != null) {
is.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
/**
* 判断文件名是否以.zip为后缀
* @param fileName 需要判断的文件名
* @return 是zip文件返回true,否则返回false
*/
public static boolean isEndsWithZip(String fileName) {
boolean flag = false;
if(fileName != null && !"".equals(fileName.trim())) {
if(fileName.endsWith(".ZIP")||fileName.endsWith(".zip")){
flag = true;
}
}
return flag;
}
如此,便实现了文件下载功能(先生成文件,再返回文件的stream,当文件为多个时,先压缩,再返回压缩文件)
参考博客: