232 lines
7.7 KiB
Java
232 lines
7.7 KiB
Java
package top.baogutang.music.service.impl;
|
||
|
||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||
import com.fasterxml.jackson.core.type.TypeReference;
|
||
import lombok.Data;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.apache.commons.lang3.StringUtils;
|
||
import org.springframework.beans.factory.annotation.Value;
|
||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||
import org.springframework.data.redis.core.RedisTemplate;
|
||
import org.springframework.http.HttpHeaders;
|
||
import org.springframework.http.HttpMethod;
|
||
import org.springframework.http.MediaType;
|
||
import org.springframework.http.ResponseEntity;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.util.CollectionUtils;
|
||
import org.springframework.web.client.RestTemplate;
|
||
import top.baogutang.music.dao.entity.MusicRecordEntity;
|
||
import top.baogutang.music.exceptions.BusinessException;
|
||
import top.baogutang.music.service.IMusicInfoService;
|
||
import top.baogutang.music.service.IMusicRecordService;
|
||
import top.baogutang.music.utils.CacheUtil;
|
||
import top.baogutang.music.utils.OkHttpUtil;
|
||
|
||
|
||
import javax.annotation.Resource;
|
||
import javax.servlet.http.HttpServletResponse;
|
||
import java.io.InputStream;
|
||
import java.io.OutputStream;
|
||
import java.util.HashMap;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.Objects;
|
||
import java.util.concurrent.Executor;
|
||
import java.util.concurrent.TimeUnit;
|
||
|
||
import static top.baogutang.music.constants.CacheKey.KEY_MUSIC_TAG_TOKEN_PREFIX;
|
||
|
||
/**
|
||
*
|
||
* @description:
|
||
* @author: N1KO
|
||
* @date: 2025/01/23 : 14:53
|
||
*/
|
||
@Slf4j
|
||
@Service
|
||
@RefreshScope
|
||
public class MusicInfoServiceImpl implements IMusicInfoService {
|
||
|
||
@Resource
|
||
private IMusicRecordService musicRecordService;
|
||
|
||
@Resource
|
||
private RestTemplate restTemplate;
|
||
|
||
@Resource
|
||
private RedisTemplate<String, Object> redisTemplate;
|
||
|
||
@Resource(name = "commonExecutor")
|
||
private Executor commonExecutor;
|
||
|
||
@Value("${baogutang.music-tag.token}")
|
||
private String tokenUrl;
|
||
|
||
@Value("${baogutang.music-tag.token.param1:username}")
|
||
private String tokenParam1;
|
||
|
||
@Value("${baogutang.music-tag.token.value1:admin}")
|
||
private String tokenValue1;
|
||
|
||
@Value("${baogutang.music-tag.token.param2:password}")
|
||
private String tokenParam2;
|
||
|
||
@Value("${baogutang.music-tag.token.value2:admin}")
|
||
private String tokenValue2;
|
||
|
||
@Value(("${baogutang.music-tag.cover}"))
|
||
private String coverUrl;
|
||
|
||
@Override
|
||
public void getCover(String title, String artist, String album, HttpServletResponse response) {
|
||
MusicRecordEntity musicRecord = musicRecordService.queryByNameOrAlbumOrArtist(title, album, artist);
|
||
if (Objects.nonNull(musicRecord) && StringUtils.isNotBlank(musicRecord.getPic())) {
|
||
this.downloadPicAndResponse(musicRecord.getPic(), response);
|
||
return;
|
||
}
|
||
|
||
// 获取三方token
|
||
String token = CacheUtil.cacheOrSupply(KEY_MUSIC_TAG_TOKEN_PREFIX,
|
||
1L,
|
||
TimeUnit.DAYS,
|
||
redisTemplate,
|
||
this::geneToken,
|
||
new TypeReference<>() {
|
||
});
|
||
Map<String, String> headers = new HashMap<>();
|
||
headers.put("authorization", "jwt " + token);
|
||
headers.put("Content-Type", "application/json");
|
||
Map<String, Object> params = new HashMap<>();
|
||
if (StringUtils.isBlank(title)) {
|
||
params.put("title", album);
|
||
} else {
|
||
params.put("title", title);
|
||
}
|
||
params.put("artist", artist);
|
||
params.put("album", album);
|
||
InfoRes<List<MusicInfoRes>> res = this.queryInfo(headers, params);
|
||
if (Objects.isNull(res) || !Boolean.TRUE.equals(res.getResult()) || CollectionUtils.isEmpty(res.getData())) {
|
||
log.error("<<<<<<<<<<query info error>>>>>>>>>>");
|
||
return;
|
||
}
|
||
MusicInfoRes musicInfoRes = res.getData().get(0);
|
||
|
||
this.downloadPicAndResponse(musicInfoRes.getAlbumImg(), response);
|
||
}
|
||
|
||
|
||
private InfoRes<List<MusicInfoRes>> queryInfo(Map<String, String> headers, Map<String, Object> params) {
|
||
InfoRes<List<MusicInfoRes>> res = null;
|
||
try {
|
||
params.put("resource", "qmusic");
|
||
res = OkHttpUtil.post(coverUrl, headers, params, new TypeReference<>() {
|
||
});
|
||
if (Objects.isNull(res) || !Boolean.TRUE.equals(res.getResult()) || CollectionUtils.isEmpty(res.getData())) {
|
||
params.put("resource", "netease");
|
||
res = OkHttpUtil.post(coverUrl, headers, params, new TypeReference<>() {
|
||
});
|
||
}
|
||
} catch (Exception e) {
|
||
log.error("query music info error:{}", e.getMessage(), e);
|
||
return null;
|
||
}
|
||
return res;
|
||
}
|
||
|
||
private String geneToken() {
|
||
Map<String, String> params = new HashMap<>();
|
||
params.put(tokenParam1, tokenValue1);
|
||
params.put(tokenParam2, tokenValue2);
|
||
TokenRes tokenRes = null;
|
||
try {
|
||
tokenRes = OkHttpUtil.post(tokenUrl, params, new TypeReference<>() {
|
||
});
|
||
} catch (Exception e) {
|
||
log.error("<<<<<<<<<<获取token异常:{}>>>>>>>>>>", e.getMessage(), e);
|
||
throw new BusinessException("获取token异常!");
|
||
}
|
||
if (Objects.nonNull(tokenRes) && Boolean.TRUE.equals(tokenRes.getResult())) {
|
||
return tokenRes.getToken();
|
||
}
|
||
throw new BusinessException("获取token异常!");
|
||
}
|
||
|
||
private void downloadPicAndResponse(String picUrl, HttpServletResponse response) {
|
||
|
||
// 获取响应实体
|
||
ResponseEntity<org.springframework.core.io.Resource> responseEntity = restTemplate.exchange(
|
||
picUrl,
|
||
HttpMethod.GET,
|
||
null,
|
||
org.springframework.core.io.Resource.class
|
||
);
|
||
|
||
// 设置Content-Type
|
||
MediaType contentType = responseEntity.getHeaders().getContentType();
|
||
if (contentType != null) {
|
||
response.setContentType(contentType.toString());
|
||
} else {
|
||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||
}
|
||
|
||
// 设置Content-Length(如果可用)
|
||
List<String> contentLength = responseEntity.getHeaders().get(HttpHeaders.CONTENT_LENGTH);
|
||
if (contentLength != null && !contentLength.isEmpty()) {
|
||
response.setHeader(HttpHeaders.CONTENT_LENGTH, contentLength.get(0));
|
||
}
|
||
if (Objects.isNull(responseEntity.getBody())) {
|
||
log.error("<<<<<<<<<<getCover error! url:{} response body is null>>>>>>>>>>", picUrl);
|
||
return;
|
||
}
|
||
try (InputStream inputStream = responseEntity.getBody().getInputStream();
|
||
OutputStream outputStream = response.getOutputStream()) {
|
||
|
||
// 数据传输
|
||
byte[] buffer = new byte[8192];
|
||
int bytesRead;
|
||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||
outputStream.write(buffer, 0, bytesRead);
|
||
}
|
||
outputStream.flush();
|
||
} catch (Exception e) {
|
||
log.error("getCover error!picUrl:{},message:{}", picUrl, e.getMessage(), e);
|
||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||
}
|
||
|
||
}
|
||
|
||
@Data
|
||
static class TokenRes {
|
||
private String token;
|
||
private Boolean result;
|
||
}
|
||
|
||
@Data
|
||
static class InfoRes<T> {
|
||
private Boolean result;
|
||
private String code;
|
||
private T data;
|
||
}
|
||
|
||
@Data
|
||
static class MusicInfoRes {
|
||
|
||
private String mid;
|
||
|
||
private String extra;
|
||
|
||
private String notice;
|
||
|
||
private String title;
|
||
|
||
private String singer;
|
||
|
||
private String album;
|
||
|
||
@JsonProperty("album_img")
|
||
private String albumImg;
|
||
|
||
private String artist;
|
||
}
|
||
}
|