探店笔记类似点评网站的评价,往往是图文结合。对应的表有两个:
- tb_blog:探店笔记表,包含笔记中标题、文字、图片等
- tb_blog_comments:其他用户对探店笔记的评价
修改文件上传路径:
由于我把 Nginx 放在了 Linux 虚拟机上,而 Java 程序则是在我本地,如果依旧使用老师讲的那种上传方式,肯定实行不通。为了实现通过 Java 代码向远程服务器上传文件,花了我两天时间。
如果想要从本地向远程服务器上传文件,需要使用 SSH 进行上传。
参考文章,感谢两位大佬:
Java用SSH2连接Linux服务器并执行命令,上传下载文件
SFTP中创建文件目录,上传文件(*)
创建工具类 SSHUtilscom.jcraft jsch 0.1.55
package com.hmdp.utils;
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class SSHUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(SSHUtils.class);
private static final int SESSION_TIMEOUT = 30 * 10000000;
public static Session createSshSession(String host, int port ,String userName, String password){
// 创建jsch对象
JSch jsch = new JSch();
Session session = null;
// 创建session会话
try {
session = jsch.getSession(userName, host, port);
// 设置密码
session.setPassword(password);
// 创建一个session配置类
Properties sshConfig = new Properties();
// 跳过公钥检测
sshConfig.put("StrictHostKeyChecking", "no");
session.setConfig(sshConfig);
// 我们还可以设置timeout时间
session.setTimeout(SESSION_TIMEOUT);
// 建立连接
session.connect();
}
catch (Exception e){
e.printStackTrace();
}
return session;
}
public static List executeCmd(Session session, String cmd) {
ChannelExec channelExec = null;
InputStream inputStream = null;
// 输出结果到字符串数组
List resultLines = new ArrayList<>();
// 创建session会话
try {
// session建立之后,我们就可以执行shell命令,或者上传下载文件了,下面我来执行shell命令
channelExec = (ChannelExec) session.openChannel("exec");
// 将shell传入command
channelExec.setCommand(cmd);
// 开始执行
channelExec.connect();
// 获取执行结果的输入流
inputStream = channelExec.getInputStream();
String result = null;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
while ((result = in.readLine()) != null) {
resultLines.add(result);
LOGGER.info("命令返回信息:{}", result);
}
} catch (Exception e) {
LOGGER.error("Connect failed, {}", e.getMessage());
ArrayList errorMsg = new ArrayList<>();
errorMsg.add(e.getMessage());
return errorMsg;
} finally {
// 释放资源
if (channelExec != null) {
try {
channelExec.disconnect();
} catch (Exception e) {
LOGGER.error("JSch channel disconnect error:", e);
}
}
if (session != null) {
try {
session.disconnect();
} catch (Exception e) {
LOGGER.error("JSch session disconnect error:", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
LOGGER.error("inputStream close error:", e);
}
}
}
return resultLines;
}
public static void uploadFile(Session session,String directory,File uploadFile,String uploadFileName){
ChannelSftp channelSftp = null;
try {
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
LOGGER.info("start upload channel file!");
channelSftp.cd(directory);
channelSftp.put(new FileInputStream(uploadFile), uploadFileName);
LOGGER.info("Upload Success!");
}
catch (Exception e){
e.printStackTrace();
} finally {
if (null != channelSftp){
channelSftp.disconnect();
LOGGER.info("end execute channel sftp!");
}
if (session != null) {
try {
session.disconnect();
} catch (Exception e) {
LOGGER.error("JSch session disconnect error:", e);
}
}
}
}
public static void uploadFile(Session session,String directory,FileInputStream inputStream,String uploadFileName){
ChannelSftp channelSftp = null;
try {
if(uploadFileName.indexOf("/") == -1){
return;
}
String[] fileSplit = uploadFileName.split("/");
if(fileSplit == null){
return;
}
String fileName = fileSplit[fileSplit.length-1];
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
LOGGER.info("start upload channel file!");
channelSftp.cd(directory);
for(int i = 0; i < fileSplit.length - 1; i++){
if("".equals(fileSplit[i])){
continue;
}
if(isDirExist(fileSplit[i] + "/", channelSftp)){
channelSftp.cd(fileSplit[i]);
} else {
// 这里要注意:通过 channelSftp.mkdir 来创建文件夹,只能一个一个创建,不能批量创建
channelSftp.mkdir(fileSplit[i] + "");
channelSftp.cd(fileSplit[i] + "");
}
}
channelSftp.put(inputStream, fileName);
LOGGER.info("Upload Success!");
}
catch (Exception e){
e.printStackTrace();
} finally {
if (null != channelSftp){
channelSftp.disconnect();
LOGGER.info("end execute channel sftp!");
}
if (session != null) {
try {
session.disconnect();
} catch (Exception e) {
LOGGER.error("JSch session disconnect error:", e);
}
}
}
}
public static boolean isDirExist(String directory, ChannelSftp sftp) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(directory);
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
public static void downloadFile(Session session, String directory,String savePathWithFileName,String downloadFileName) {
ChannelSftp channelSftp = null;
try {
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
LOGGER.info("start download channel file!");
channelSftp.cd(directory);
File file = new File(savePathWithFileName);
channelSftp.get(downloadFileName, new FileOutputStream(file));
LOGGER.info("Download Success!");
}
catch (Exception e){
e.printStackTrace();
} finally {
if (null != channelSftp){
channelSftp.disconnect();
LOGGER.info("end execute channel sftp!");
}
if (session != null) {
try {
session.disconnect();
} catch (Exception e) {
LOGGER.error("JSch session disconnect error:", e);
}
}
}
}
}
修改 UploadController
@Slf4j
@RestController
@RequestMapping("upload")
public class UploadController {
@PostMapping("blog")
public Result uploadImage(@RequestParam("file") MultipartFile image, HttpServletRequest request) {
try {
// 获取原始文件名称
String originalFilename = image.getOriginalFilename();
// 生成新文件名
String fileName = createNewFileName(originalFilename);
FileInputStream inputStream = (FileInputStream) image.getInputStream();
Session SSHSESSION = SSHUtils.createSshSession("ip地址", 22, "远程服务器用户名", "远程服务器密码");
SSHUtils.uploadFile(SSHSESSION, SystemConstants.IMAGE_UPLOAD_DIR ,inputStream, fileName);
// 返回结果
log.debug("文件上传成功,{}", fileName);
return Result.ok(fileName);
} catch (IOException e) {
throw new RuntimeException("文件上传失败", e);
}
}
private String createNewFileName(String originalFilename) {
// 获取后缀
String suffix = StrUtil.subAfter(originalFilename, ".", true);
// 生成目录
String name = UUID.randomUUID().toString();
int hash = name.hashCode();
int d1 = hash & 0xF;
int d2 = (hash >> 4) & 0xF;
// 判断目录是否存在
String pathName = SystemConstants.IMAGE_UPLOAD_DIR + StrUtil.format("/blogs/{}/{}", d1, d2);
// 生成文件名
return StrUtil.format("/blogs/{}/{}/{}.{}", d1, d2, name, suffix);
}
}
常量类 SystemConstant
public class SystemConstants {
public static final String IMAGE_UPLOAD_DIR = "/usr/local/nginx/html/hmdp/imgs/";
}
然后就可以愉快地上传文件啦!
1.3 前端代码修改我在上传完探店笔记后,发现个人主页加载不出来照片,看了下前端访问路径,是访问路径出了问题,前端页面多加了一个 /imgs/ 路径。
打开 info.html ,将多余的 /imgs/ 删除即可。
可以重新下载前端项目,应该是后来又重新上传了,这几个问题都解决。



