spring 实现小程序抖音去水印后台
由于网上大量源码都是使用php实现的,大部分加密或者压缩,本人不懂php也不想学习php
实现原理
由于微信小程序服务端,必须使用https 进行解析,这就说明域名必须是备案的,想要获得不错的延时,那就必须使用国内的服务器,那就说明服务器也要备案。
觉得比较麻烦的小伙伴可以,尝试玩耍,切勿较真。
本教程针对于小程序后台实现
说明
- 在网上随便找个支持解析抖音无水印解析的网站,根据需求获得想要的json数据
- 使用小程序实现,那就有一个避不开的问题,下载地址必须是 https 而且 【抖音无水印解析地址】并不是固定的,大部是CDN链接,过了10min左右就会失效。所以必须换成自己搭建的固定的备案域名。
后台实现思路
- 【前台小程序】获取无水印下载链接返回给【后台】
- 通过redis 缓存唯一标识符 并返回给小程序(用于小程序特定下载API)
- 响应前台下载请求,通过小程序特定的下载API,响应下载并缓存到手机
/**
* @author Amewin
* @date 2020/11/7 20:57
* @description : 去水印类
*/
@RestController
@RequestMapping("/report")
public class ReportController {
@Autowired
private JedisPool jedisPool;
private static String contentType = "video/mp4";
private static String disposition = "attachment;filename=003.mp4";
/**
* 将无水印保存进入redis
* @param url 无水印解析地址
* @return
*/
@RequestMapping("/setPath")
public String setPath(@RequestBody Map url) {
String uuid = UUID.randomUUID().toString();
String urlName = (String) url.get("url");
//获取redis 连接对象
Jedis resource = jedisPool.getResource();
//切換Redis資料庫
resource.select(2);
//设置缓存 key-vaule
resource.set(uuid, urlName);
//获取指定范围随机时间
int expiryTime= ThreadLocalRandom.current().nextInt(180, 270);
//设置缓存失效时间
resource.expire(uuid, expiryTime);
return uuid;
}
/**
* 去水印文件下载
* @param response 写入请求头用于回调
* @param uuid
* @return
*/
@RequestMapping("/getFile")
private String getFile(HttpServletResponse response, String uuid) {
Jedis resource = jedisPool.getResource();
resource.select(2);
String urlPath = resource.get(uuid);
String file = null;
if (StringUtils.isEmpty(urlPath)) {
file = this.getFile(response, urlPath, contentType, disposition);
}
return file;
}
/**
* @param response
* @param url 下载路径
* @param contentType 下载响应头 --> 响应格式 audio/mpeg | video/mp4 | image/jpeg
* @param disposition 下载响应头 --> 响应文件名称 attachment;filename=003.jpg | 003.MP4| 003.mp3
* @return
*/
private String getFile(HttpServletResponse response, String url, String contentType, String disposition) {
OutputStream out = null;
InputStream inputStream = null;
try {
UrlResource urlResource = new UrlResource(url);
response.reset();
inputStream = urlResource.getInputStream();
byte[] bytes = IOUtils.toByteArray(inputStream);
if (bytes.length > 61440) {
//61440 60mb
out.close();
inputStream.close();
return "下载文件过大";
}
out = response.getOutputStream();
// response.setContentType("audio/mpeg");
// response.setHeader("content-Disposition", "attachment;filename=music.mp3");
// response.setContentType("video/mp4");
// response.setHeader("content-Disposition", "attachment;filename=video.mp4");
// response.setContentType("image/jpeg");
// response.setHeader("content-Disposition", "attachment;filename=003.jpg");
response.setContentType(contentType);
response.setHeader("content-Disposition", disposition);
out.write(bytes);
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
小程序后台实现js
//获取应用实例
var app = getApp(),
n = ''
Page({
data: {
videoSrc: '',
dataUrl: ''
},
onLoad: function() {
this.getdataUrl('dataUrl')
this.setData({
videoSrc: app.globalData.videoSrc,
dataUrl: this.getdataUrl('dataUrl')
})
},
download: function() {
var t = this,
e= t.data.dataUrl
wx.request({
url: 'http://localhost:82/report/setPath.do',
method: 'post',
data: {
url: e
},
success: function(p) {
if (p.data !=null) {
wx.showLoading({
title: '保存中 0%'
}), (n = wx.downloadFile({
url: 'http://localhost:82/report/getFile.do?url=' + p.data,
success: function (o) {
wx.hideLoading(), wx.saveVideoToPhotosAlbum({
filePath: o.tempFilePath,
success: function (o) {
t.showToast('保存成功,返回!', 'success', 1000), setTimeout(function () {
wx.setClipboardData({
data: null,
})
}, 1000)
},
fail: function (o) {
t.showToast('保存失败')
}
})
},
fail: function (o) {
n = null, wx.hideLoading(), t.showToast('下载失败')
}
})).onProgressUpdate(function (o) {
100 === o.progress ? '' : wx.showLoading({
title: '保存中 ' + o.progress + '%'
})
})
}
},
fail: function(t) {
wx.hideLoading(), a.showToast('解析失败')
}
})
},
showToast: function(o) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 'none',
n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1500
wx.showToast({
title: o,
icon: t,
duration: n
})
}
})