springboot和vue构建文件的下载
程序员文章站
2022-05-30 21:25:59
...
一.简介:做一个文件下载功能前后端都可以随便玩,这次主要做的是html的下载,其中html是从别人那里找到的,忘记了原链接,反正挺好看的,适合用于表白。
二.整体的构建:首先看下别人的html文件
html链接
打开效果是个动态的图片.
我敲,这他妹的也太好看了吧,大佬膜拜下。
然后可以分析下他的源码,我打算修改它的时间和对应表白人还有自己的姓名与标题名,其他的写的挺不错的就懒得改了。大概就是爱心里面的内容。
源码要改的
a.表白的人和自己
<div id="loveHeart">
<canvas id="garden"></canvas>
<div id="words">
<div id="messages">
***,I LOVE YOU!
<div id="elapseClock"></div>
</div>
<div id="loveu">
Love u forever and ever.<br/>
<div class="signature">- LXL</div>
</div>
</div>
</div>
b.标题
<title>I Love ***</title>
c.时间
时间的计算,是当前时间减去认识的时间,所以一直在变化了。
var offsetX = $("#loveHeart").width() / 2;
var offsetY = $("#loveHeart").height() / 2 - 55;
var together = new Date();
together.setFullYear(2019, 8, 25);
together.setHours(0);
together.setMinutes(0);
together.setSeconds(0);
together.setMilliseconds(0);
d.看了下我们只要设置前端传四个参数,然后后端接收生成一个新的html,并返回展示给前端,我敲好简单的样子,确实不过对于我这种vue菜鸟就有点难搞了。
三。代码的编写
a.后端代码
写一个生成html的方法,在写一个获取html的方法。
Controller层
package com.example.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.enetity.ResponseBean;
import com.example.demo.service.LoveHtmlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@CrossOrigin
@RestController
@RequestMapping("/love")
public class LoveHtmlController {
@Autowired
LoveHtmlService loveHtmlService;
/**
* 用于生成html
* @param httpServletResponse
* @param jsonObject
* @return
*/
@PostMapping(value = "/html/create")
public ResponseBean createFile(HttpServletResponse httpServletResponse, @RequestBody JSONObject jsonObject){
return loveHtmlService.createHtmleFile(jsonObject,httpServletResponse);
}
/**
* 用于get下载html
* @param httpServletResponse
* @param jsonObject
* @return
*/
@GetMapping(value = "/html/down1")
public ResponseBean createFile1(HttpServletResponse httpServletResponse, HttpServletRequest request){
String downName = request.getParameter("downName");
return loveHtmlService.downLoad(downName,httpServletResponse);
}
/**
* 用于post下载html
* @param httpServletResponse
* @param jsonObject
* @return
*/
@PostMapping(value = "/html/down")
public ResponseBean getDownFile(HttpServletResponse httpServletResponse, @RequestBody JSONObject jsonObject){
String downName = jsonObject.getString("downName");
return loveHtmlService.downLoad(downName,httpServletResponse);
}
}
2.Service层
package com.example.demo.service;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.enetity.ResponseBean;
import javax.servlet.http.HttpServletResponse;
public interface LoveHtmlService {
ResponseBean downLoad(String downLoad, HttpServletResponse httpServletResponse);
ResponseBean createHtmleFile(JSONObject jsonObject, HttpServletResponse httpServletResponse);
}
3.实现类`
package com.example.demo.service.impl;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.enetity.ResponseBean;
import com.example.demo.service.LoveHtmlService;
import com.example.demo.util.CommonUtils;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Calendar;
import java.util.Date;
@Service
public class LoveHtmlServiceImpl implements LoveHtmlService {
@Override
public ResponseBean downLoad(String downLoad, HttpServletResponse httpServletResponse) {
//这个是生成的html的地址
String s = "D:\\demo\\config\\"+downLoad+".html";
File file = new File(s);
Date date = DateUtil.date(Calendar.getInstance());
String s1 = DateUtil.formatTime(date);
try {
FileInputStream fileInputStream = new FileInputStream(file);
//以HTTPResponse返回给前端
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setHeader("Content-Disposition","attachment;filename="+downLoad+s1+".html");
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
byte[] data= new byte[1024];
int len;
while ((len=fileInputStream.read(data))>0){
outputStream.write(data,0,len);
}
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return CommonUtils.succssonJson();
}
@Override
public ResponseBean createHtmleFile(JSONObject jsonObject, HttpServletResponse httpServletResponse) {
//这个是原来的html的地址
String s = "D:\\demo\\config\\I LOVE YOU.html";
File file = new File(s);
//这个方法会把html不包含在内所以后面需要再加上这个。
String head = readHtmlTitle(file, "html");
File file1 = new File(file.getPath().replace("I LOVE YOU", "LOVE"));
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file1);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//用于那四个页面元素的改变
String yyyyMMdd = jsonObject.getString("times");
String Time =yyyyMMdd.substring(0,4)+","+yyyyMMdd.substring(4,6)+","+yyyyMMdd.substring(6);
String content = jsonObject.getString("content");
String content1 = jsonObject.getString("content1");
String content2 = jsonObject.getString("content2");
head = head.replace("together.setFullYear(2019, 8, 25);", "together.setFullYear("+Time+");");
head=head.replace("I Love ***",content);
head=head.replace(" ***,I LOVE YOU!",content1);
head=head.replace("LXL",content2);
String head1= "<!DOCTYPE HTML>\n" +
"<html lang=\"en\">"+head+"</html>";
try {
fileOutputStream.write(head1.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
openmHtml("D:\\demo\\config\\LOVE.html");
} catch (Exception e) {
e.printStackTrace();
}
return CommonUtils.succssonJson();
}
public static String readHtmlTitle(File file, String title) {
String text = "";
try {
FileInputStream iStream = new FileInputStream(file);
Reader reader = new InputStreamReader(iStream);
BufferedReader htmlReader = new BufferedReader(reader);
String line;
boolean found = false;
while (!found && (line = htmlReader.readLine()) != null) {
if (line.toLowerCase().indexOf("<" + title) != -1) { // 在<body>的前面可能存在空格
found = true;
}
}
found = false;
while (!found && (line = htmlReader.readLine()) != null) {
if (line.toLowerCase().indexOf("</" + title) != -1) {
found = true;
} else {
// 如果存在图片,则将相对路径转换为绝对路径
String lowerCaseLine = line.toLowerCase();
if (lowerCaseLine.contains("src")) {
String directory = "D:/test";
String[] splitLines = line.split("<img\\s+"); // <img后带一个或多个空格
// 因为java中引用的问题不能使用for each
for (int i = 0; i < splitLines.length; i++) {
if (splitLines[i].toLowerCase().startsWith("src")) {
splitLines[i] = splitLines[i].substring(0, splitLines[i].toLowerCase().indexOf("src") + 5)
+ directory
+ splitLines[i].substring(splitLines[i].toLowerCase().indexOf("src") + 5);
}
}
// 最后进行拼接
line = "";
for (int i = 0; i < splitLines.length - 1; i++) { // 循环次数要-1,因为最后一个字符串后不需要添加<img
line = line + splitLines[i] + "<img ";
}
line = line + splitLines[splitLines.length - 1];
}
text = text + line + "\n";
}
}
} catch (Exception e) {
}
return text;
}
public static void openmHtml(String url) throws Exception {
// 谷歌浏览器的地址,用于打开html文件
ProcessBuilder proc = new ProcessBuilder("C:\\Users\\86159\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe", url);
proc.start();
}
}
a1.后端代码的单元测试
通过postman发请求,我的端口是8090
然后请求成功,同时打开页面
都改了,哈哈。
然后对于下载接口发送请求
值得注意的是response是一个html文件的字符串。
b。届时后端代码已经完成了,就差前端了。
<template>
<div class="index">
<h1>创建展示html</h1>
<div>时间<input type="input" id="times" v-model="times"></div>
<div>文本<input type="input" id="content" v-model="content"></div>
<div>文本1<input type="input" id="content1" v-model="content1"></div>
<div>文本2<input type="input" id="content2" v-model="content2"></div>
<div class="block" v-on:click="createHtml"></div>
<input type="input" id="downName" v-model="downName"><br/>
<div class="block" v-on:click="downHtml"></div>
<div class="block1" v-on:click="testGet1"></div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'App',
data() {
return {
times: '',
content: '',
content1: '',
content2: '',
downName: '',
test:""
}
},
methods: {
post(url, params, name, header, functionName) {
axios.post("http://localhost:8090" + url, params,
header
).then(resp => {
this.data = resp.data
alert(this.data)
if (this.data.retCode == "1") {
functionName()
} else {
//alert(resp.data.retMsg);
}
}).catch(err => {
console.log('请求失败:' + err.status + ',' + err.statusText);
});
},
post1(url, params, name, header, functionName) {
axios.post("http://localhost:8090" + url, params,
header
).then(resp => {
this.data = resp.data
functionName()
}).catch(err => {
console.log('请求失败:' + err.status + ',' + err.statusText);
});
},
createHtml() {
this.post('/love/html/create', {
times: this.times,
content: this.content,
content1: this.content1,
content2: this.content2
}, "生成html成功", {})
},
get(url, params, name, header, functionName) {
axios.get("http://192.168.203.1:8090" + url, params,
header
).then(resp => {
this.data = resp.data
if (this.data.retCode == "1") {
functionName()
} else {
//alert(resp.data.retMsg);
}
}).catch(err => {
console.log('请求失败:' + err.status + ',' + err.statusText);
});
},
testGet1() {
this.downName = 'LOVE'
axios.get('http://192.168.203.1:8090/love/html/down1', {
params: {
downName: 'LOVE'
}
})
.then(resp => {
//this.windowMethod() //用open的方式对get请求再发一次请求会下载html
//this.test=resp.data
let result = this.dataToExcelFile({data: resp.data, type: 'application/html', fileName: 'LOVE.html'}) //用流的操作写入到文件中
//let result1=this.dataToFile({data: resp.data, type: 'application/html', fileName: 'LOVE.html'})
})
.catch(function (error) {
console.log(error);
})
},
testGet() {
this.post1('/love/html/down', {
downName: this.downName
}, "下载成功", {}, this.windowMethod)
},
downHtml() {
this.post1('/love/html/down', {
downName: this.downName
}, "下载成功", {}, this.windowMethod)
},
windowMethod() {
//地址需要自己修改哦
window.location.href = "http://localhost:8090/love/html/down1?downName=" + this.downName
},
dataToExcelFile(param) {
let data = param.data;
let type = param.type;
let fileName = param.fileName;
let blob = new Blob([data], {type: type});
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, fileName);
} else {
let url = window.URL.createObjectURL(blob);
let link = document.createElement('a');
link.style.display = "none";
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
}
return '0'
},
dataToFile(param) {
let data = param.data;
let type = param.type;
let fileName = param.fileName;
if (typeof data == 'string') {
let bstr = data;
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n]=bstr.charCodeAt(n)
}
let blob=new Blob([u8arr],{type:type});
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, fileName);
} else {
let url = window.URL.createObjectURL(blob);
let link = document.createElement('a');
alert(url);
window.open(url);
}
return '0'
} else {
return '1'
}
}
}
}
</script>
<style scoped>
.block {
height: 20px;
width: 100px;
background-color: blue;
margin: 0 auto;
}
.block1 {
height: 20px;
width: 100px;
background-color: blanchedalmond;
margin: 0 auto;
}
.white {
height: 200px;
width: 400px;
background-color: white;
margin: 0 auto;
}
</style>
b1的测试
点击第一个蓝框,页面效果
哈哈,我可真厉害呢,创建html好了,该下载了
点击第二个蓝框,用post请求实现
下载的时候带了一个时间戳。
点粉色的,用get请求实现,后台的逻辑也是一样,但是get懒得写时间戳了就这样
四。总结这就基本完成了前后端文件下载与新建的了,不过没有base64加密,不是很安全,但是挺不错的,就是自己前端技术太菜了,需要一些前端的精美照片。加油吧骚年