項目結構圖
相較于上次新增集中在這些地方:
🚀?上傳音樂的核心流程
-
前端投遞:用戶填寫歌手名 + 選擇MP3文件
-
后端接收:
/music/upload
?接口化身音樂快遞員 -
安全驗證:先查用戶是否“持證上崗”(登錄態)
-
倉庫選址:把音樂存到服務器的“音樂保險柜”(暫時就是存在自己的電腦)
-
數據庫登記:給音樂辦張“身份證”(標題、歌手、存儲路徑等)
?接口預覽設計:
請求: { post, /music/upload {singer,MultipartFilefile}, }
響應: { "status":0, "message":"上傳成功!", "data":true }
🔍?技術揭秘:關鍵代碼與騷操作
???1. 接口設計:音樂快遞簽收單
實體類:新建Music類
import lombok.Data;@Datapublic class Music {private int id;private String title;private String singer;private String url;private String time;private int userid;
}
Controller層:MusicController
@RestController
@RequestMapping("/music")
public class MusicController {@Value("${music.local.path}")private String SAVE_PATH;@Resourceprivate MusicMapper musicMapper;@RequestMapping(value = "/upload")public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer,@RequestParam("filename") MultipartFile file,HttpServletRequest req,HttpServletResponse resp) throws IOException {//無session就不創建HttpSession httpSession = req.getSession(false);if (httpSession == null || httpSession.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄!");return new ResponseBodyMessage<>(-1, "沒有登錄!", false);}String filenameAndType = file.getOriginalFilename();System.out.println("filenameAndType---->>>>>>>>>>" + filenameAndType);String path = SAVE_PATH + "\\ " + filenameAndType;File dest = new File(path);System.out.println("dest:=>" + dest.getPath());if (!dest.exists()) {dest.mkdirs();}try {file.transferTo(dest);} catch (IOException e) {e.printStackTrace();return new ResponseBodyMessage<>(-1, "上傳失敗", false);}//數據庫當中存儲的歌曲不包括.mp3.所以需要進行截取String title = filenameAndType.substring(0, filenameAndType.lastIndexOf("."));//SimpleDateFormat來格式化當前的系統時間SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");String time = sf.format(new Date());//這里會被用到 播放音樂的模塊String url = "/CloudMusic/get?path="+title;User user =(User)httpSession.getAttribute(Constant.USERINFO_SESSION_KEY);int userId = user.getId();int ret = musicMapper.insert(title,singer,time,url,userId);if(ret == 1){}else{dest.delete();return new ResponseBodyMessage<>(-1,"數據庫上傳失敗,刪除上傳的?樂!",false);}return new ResponseBodyMessage<>(0,"上傳成功!",true);}
}
String url = "/CloudMusic/get?path="+title;
注意這個地方的? ? ? ?路徑/http請求方法
注解介紹:
1. 使?@Value("${music.local.path}"),獲取到配置?件當中的值。不建議中?路徑。
#?樂上傳后的路徑?music.local.path=D:/work/local/music
2. MultipartFile類,在org.springframework.web.multipart包當中,是Spring框架中處理?件上傳 的主要類。
接口層:MusicMapper? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 現在還未將數據插?到數據庫當中,接下來我們實現數據庫中 數據的寫?。? ? ? ? ? ? ? ? ? ? ? ? ? ??
?
@Mapper
public interface MusicMapper {int insert(String title,String singer,String time,String url,int userid);}
?定義MusicMapper.xml
<mapper namespace="com.example.musicplayer.mapper.MusicMapper"><insert id="insert">insert into music(title,singer,time,url,userid)values(#{title},#{singer},#{time},#{url},#{userid})</insert>
</mapper>
注意自己的文件名
基于此這個插入一個.MP3形式文件到數據庫的接口就已經完成了
我們其實可以看到在我們的service中是寫下了這樣一段邏輯的
HttpServletResponse resp) throws IOException {//沒有session不創建 HttpSession httpSession = req.getSession(false);if(httpSession == null ||
httpSession.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄!");return new ResponseBodyMessage<>(-1,"沒有登錄!",false);}
同時還有一些配置要記得配置,我的這個配置文件如下
application.propertied <用來對照>
#配置數據庫
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/musicserver?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=com.mysql.jdbc.Driver#配置xml
mybatis.mapper-locations=classpath:mybatis/**Mapper.xml#配置springboot上傳文件的大小,默認每個文件的配置最大為15Mb,單次請求的文件的總數不能大于100Mb
spring.servlet.multipart.max-file-size = 15MB
spring.servlet.multipart.max-request-size=100MB#音樂上傳后的路徑
music.local.path=D:/CloudMusic
#music.local.path=/home/gb/music# 配置springboot日志調試模式是否開啟
debug=true
# 設置打印日志的級別,及打印sql語句
#日志級別:trace,debug,info,warn,error
#基本日志
logging.level.root=INFO
logging.level.com.example.onlinemusic.mapper=debug
#掃描的包:druid.sql.Statement類和frank包
logging.level.druid.sql.Statement=DEBUG
logging.level.com.example=DEBUG
于是我們看到當我們在postman中測試的時候是無法直接調用這個insertMusic接口的
于是我們可以知道?
測試場景 | 請求姿勢 | 結果 |
---|---|---|
未登錄上傳 | 不傳Session | ? “請先登錄!” |
上傳偽造MP3(你可以做這個效果) | 把.txt改成.mp3 | ? “假MP3警告!” |
正常上傳 | 歌手名+真實MP3文件 | ? 成功入庫! |
同名文件覆蓋(你可以做這個效果) | 再次上傳相同文件 | ? 需自行處理重復! |
?
?
💡 一些總結
-
事務性操作:文件存盤 + 數據庫登記 = 原子操作(要么全成功,要么回滾)
-
路徑解耦:
@Value
?動態讀取存儲路徑,搬家不用改代碼! -
安全防線:Session驗證 + 文件類型檢測(雖然檢測邏輯要自己補全😉)
-
擴展空間:
-
加文件去重?👉?
SELECT * FROM music WHERE title=?
-
加音樂元數據解析?👉 用?JAudiotagger?庫讀ID3標簽!
-
相對于上次的提交,提交文件如下:
代碼倉庫:插入音樂接口開發 7.22 /音樂服務器 - Gitee.com?