今天自己做项目,遇到一个图片上传的功能。一开始我以为很简单,只要前端input拿到本地图片的地址后存到数据库,然后再渲染出来就ok了,尝试后才发现真的是自己想多了hahaha。
上面的想法存在几个问题:
1、拿不到本地的图片地址。input选择图片上传后,浏览器打开页面检查发现地址是http://localhost:xxxxxxxxxx
,此时这个地址复制到浏览器打开是可以访问的,但是刚刚那个前端页面关闭后,这个地址就不可以访问了,也找了很多资料为什么拿不到本地图片的路径,基本上的说法是浏览器自身的安全性,不会暴露本地图片的地址,防止被恶意篡改。
2、即使拿到了,在<image src="" />
标签的src中输入全路径也是渲染不出来的,只能渲染出该项目路径下的图片。
下面圆规正转!!!
第一步:java代码将图片上传到服务器。
第二步:直接访问服务器的图片资源。
第一步
1、添加依赖
<!--sftp文件上传-->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
2、java代码
package com.xl.pet.util;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.springframework.stereotype.Component;
import java.io.OutputStream;
@Component
public class UploadImage {
/**
* 利用JSch包实现SFTP上传文件
* @param bytes 文件字节流
* @param fileName 文件名
* @throws Exception
*/
public static void sshSftp(byte[] bytes,String fileName) throws Exception{
int port = 22;
String user = "xxx";
String password = "xxx";
String ip = "xxx";
// 服务器保存路径
String filepath = "/home/image";
Session session = null;
Channel channel = null;
JSch jSch = new JSch();
if(port <=0){
//连接服务器,采用默认端口
session = jSch.getSession(user, ip);
}else{
//采用指定的端口连接服务器
session = jSch.getSession(user, ip ,port);
}
//如果服务器连接不上,则抛出异常
if (session == null) {
throw new Exception("session is null");
}
//设置登陆主机的密码
session.setPassword(password);//设置密码
//设置第一次登陆的时候提示,可选值:(ask | yes | no)
session.setConfig("userauth.gssapi-with-mic","no");
session.setConfig("StrictHostKeyChecking", "no");
//设置登陆超时时间
session.connect(30000);
OutputStream outstream = null;
try {
//创建sftp通信通道
channel = (Channel) session.openChannel("sftp");
channel.connect(1000);
ChannelSftp sftp = (ChannelSftp) channel;
//进入服务器指定的文件夹
sftp.cd(filepath);
//以下代码实现从本地上传一个文件到服务器,如果要实现下载,对换一下流就可以了
outstream = sftp.put(fileName);
outstream.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
//关流操作
if (outstream != null) {
outstream.flush();
outstream.close();
}
if (session != null) {
session.disconnect();
}
if (channel != null) {
channel.disconnect();
}
System.out.println("上传成功!");
}
}
}
3、测试上传
package com.xl.pet.controller;
import com.xl.pet.util.UUIDUtils;
import com.xl.pet.util.UploadImage;
import java.io.*;
public class ImageController {
public static void main(String[] args) throws Exception{
File file = new File("C:\\Users\\86177\\Desktop\\0.jpg");
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream in = new BufferedInputStream(fileInputStream);
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] temp = new byte[1024];
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
in.close();
byte[] content = out.toByteArray();
UploadImage.sshSftp(content, UUIDUtils.getUUID()+".jpg");
}
}
此时运行后查看服务器,确实上传到/home/image/
路径下了。
第二步
现在万事俱备,只欠东风!我们只需要能够访问到服务器的图片就可以啦!
方式一
我用的是nginx反向代理。
1、服务器安装nginx
本来我想说这个网上有很多,一搜一大堆,我就不说了。后来想想自己一开始新手小白什么都不懂的时候,往往到了这一步,作者说网上有很多就不说了…然后这一步又要去搜别的,就特别麻烦,而且有时候两步操作有可能版本不一致或者其他的原因导致按照文档操作下来结果不对…心态炸裂…
好了废话不多说,直接上代码!
我个人nginx的安装方式如下:
编写yum源文件
[root@localhost etc]# vi /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
安装nginx
[root@localhost etc]# yum install -y nginx
备份nginx的配置文件
[root@localhost etc]# echo y|cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.default
启动nginx,设置为开机自启动
[root@localhost conf.d]# systemctl start nginx
[root@localhost conf.d]# systemctl enable nginx
[root@localhost conf.d]# systemctl status nginx
运行成功后打开浏览器访问http://xxxxx:80
看到界面后表示运行成功!
ps: 如果状态显示成功运行,但是浏览器访问不到,去服务器查看一下是不是80端口没有开放,我就是这个原因…
2、修改nginx的配置文件
cd /etc/nginx
,然后修改配置文件
首先说一下自己踩过的坑,上面#就是被我注释掉的,一开始修改完之后启动nginx报错,找了半天也发现有可能是配置文件格式不对,然后输入命令nginx -t
发现确实不对…后来看到最后有一行include /etc/nginx/conf.d/*.conf;
突然醒悟,然后来到/conf.d
文件夹下,发现有个配置文件,打开后
注释掉原来的location,新增后就可以访问啦!
此时请求80端口后,nginx会反向代理查找/home/image
下的资源。
http:x.x.x.x:80/image/0.jpg
成功访问!!!
又尝试了两种,特来更新!!!
方式二
通过springboot后台端口直接访问静态资源
1、引入spring-webmvc依赖
<!--静态资源访问-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
2、配置类
package com.xl.pet.controller;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class Config implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/image/**")
.addResourceLocations("file:"+"/home/image/");
}
}
/image/** 表示请求拦截
addResourceLocations表示静态资源路径
一定要加上file:
前缀!!!
一定要加上file:
前缀!!!
一定要加上file:
前缀!!!
个人理解:直接写/home/image/
时,会访问项目的resources->home->image
文件夹下的静态资源,加上"file:"
应该是系统的根目录开始,个人猜测
方式三
和方式二原理一样,但是比方式二配置更加简单。
将方式二中的配置类去掉,直接在application.properties或者application.yml文件中加上两行配置
# 静态资源访问
spring.mvc.static-path-pattern=/image/**
spring.web.resources.static-locations=file:/home/image/
大功告成!!!