本文使用java代码实现图片远程上传到linux的图片服务器上。

前提:linux安装好了ftp模块,nginx服务器,搭建好了图片服务器,可以远程访问

搭建图片服务器《一》-linux安装ftp组件

搭建图片服务器《二》-linux安装nginx

搭建图片服务器《三》:linux上nginx+ftp搭建图片服务器



一个需求

通过springMVC接受图片文件然后上传到图片服务器,把图片在图片服务器上的相对路径(不包括图片服务器的ip,防止图片服务器ip改变)保存在数据库中

实现环境:前台上传图片组件+springMVC+spring+mybatis+mysql


引入依赖

需要导入相关jar包,这里使用maven管理,导入依赖:

    <!-- 加入上传文件组件 -->
    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
    <dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>3.3</version>
    </dependency>


由于上传文件需要图片服务器相关的配置信息,这里为了不硬编码在代码中,模仿数据库连接信息的方式配置在配置文件中,然后交给spring进行管理

图片服务器需要的配置的配置文件放在classpath下:

ftp.properties

#ftp相关配置  
FTP_ADDRESS=192.168.1.113
FTP_PORT=21
FTP_USERNAME=ftpuser_album
FTP_PASSWORD=123456
FTP_BASEPATH=/home/ftpuser_album/www/album_images
#图片服务器相关配置 
IMAGE_BASE_URL=http://192.168.1.113/album_images

配置文件内容让spring读取到容器中,然后存储在实体类中:

spring配置

    <!-- 加载多个配置文件 -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:db.properties</value>
                <value>classpath:ftp.properties</value>
                <value>classpath:redis.properties</value>
            </list>
        </property>
    </bean>

springMVC配置文件需要配置上传文件的bean

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"></property>
        <property name="maxUploadSize" value="10485760000"></property>
        <property name="maxInMemorySize" value="40960"></property>
    </bean>



实体类:FtpConfig.java

@Component
public class FtpConfig {
	
    /**
     * 获取ip地址  
     */
    @Value("${FTP_ADDRESS}")
    private String FTP_ADDRESS; 
    
    /**
     * 端口号  
     */
    @Value("${FTP_PORT}")
    private String FTP_PORT; 
    
    /**
     * 用户名  
     */
    @Value("${FTP_USERNAME}")
    private String FTP_USERNAME; 
    
    /**
     * 密码  
     */
    @Value("${FTP_PASSWORD}")
    private String FTP_PASSWORD;  
    
    /**基本路径  
     */
    @Value("${FTP_BASEPATH}")
    private String FTP_BASEPATH;  
    
    /**
     * 下载地址地基础url  
     */
    @Value("${IMAGE_BASE_URL}")
    private String IMAGE_BASE_URL;

...set和get方法就省略
}

这样哪里需要使用图片服务器配置信息就可以通过@AutoWired注入FtpConfig对象即可


上传案例

上传的工具类:

public class FtpUtil {

    /**
     * ftp上传图片方法
     *title:pictureUpload
     *@param ftpConfig  由spring管理的FtpConfig配置,在调用本方法时,可以在使用此方法的类中通过@AutoWared注入该属性。由于本方法是静态方法,所以不能在此注入该属性
     *@param picNewName 图片新名称--防止重名 例如:"1.jpg"
     *@param picSavePath 图片保存路径。注:最后访问路径是 ftpConfig.getFTP_ADDRESS()+"/images"+picSavePath
     *@param file 要上传的文件(图片)
     *@return 若上传成功,返回图片的访问路径,若上传失败,返回null
     * @throws IOException
     */
    public static String pictureUploadByConfig(FtpConfig ftpConfig,String picNewName,String picSavePath,InputStream inputStream) throws IOException{

        String picHttpPath = null;


        boolean flag = uploadFile(ftpConfig.getFTP_ADDRESS(), ftpConfig.getFTP_PORT(), ftpConfig.getFTP_USERNAME(),
                ftpConfig.getFTP_PASSWORD(), ftpConfig.getFTP_BASEPATH(), picSavePath, picNewName, inputStream);

        if(!flag){
            return picHttpPath;
        }

        //picHttpPath = ftpConfig.getFTP_ADDRESS()+"/images"+picSavePath+"/"+picNewName;
        picHttpPath = ftpConfig.getIMAGE_BASE_URL()+picSavePath+"/"+picNewName;
        System.out.println("==="+picHttpPath);
        return picHttpPath;
    }
	
	
	
	
	/**  
     * Description: 向FTP服务器上传文件  
     * @param host FTP服务器hostname  
     * @param port FTP服务器端口  
     * @param username FTP登录账号  
     * @param password FTP登录密码  
     * @param basePath FTP服务器基础目录 
     * @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath 
     * @param filename 上传到FTP服务器上的文件名  
     * @param input 输入流  
     * @return 成功返回true,否则返回false  
     */    
    public static boolean uploadFile(String host, String ftpPort, String username, String password, String basePath,  
            String filePath, String filename, InputStream input) {
    	int port = Integer.parseInt(ftpPort);
        boolean result = false;  
        FTPClient ftp = new FTPClient();  
        try {  
            int reply;  
            ftp.connect(host, port);// 连接FTP服务器  
            // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器  
            ftp.login(username, password);// 登录  
            reply = ftp.getReplyCode();  
            if (!FTPReply.isPositiveCompletion(reply)) {  
                ftp.disconnect();  
                return result;  
            }  
            //切换到上传目录  
            if (!ftp.changeWorkingDirectory(basePath+filePath)) {  
                //如果目录不存在创建目录  
                String[] dirs = filePath.split("/");  
                String tempPath = basePath;  
                for (String dir : dirs) {  
                    if (null == dir || "".equals(dir)) continue;  
                    tempPath += "/" + dir;  
                    if (!ftp.changeWorkingDirectory(tempPath)) {  
                        if (!ftp.makeDirectory(tempPath)) {  
                            return result;  
                        } else {  
                            ftp.changeWorkingDirectory(tempPath);  
                        }  
                    }  
                }  
            }  
            //设置上传文件的类型为二进制类型 
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            ftp.enterLocalPassiveMode();//这个设置允许被动连接--访问远程ftp时需要
            //上传文件  
            if (!ftp.storeFile(filename, input)) {  
                return result;  
            }  
            input.close();  
            ftp.logout();  
            result = true;  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (ftp.isConnected()) {  
                try {  
                    ftp.disconnect();  
                } catch (IOException ioe) {  
                }  
            }  
        }  
        return result;  
    }  
      
    
    
    //下载文件方法不用看,可能日后有用,先留在这里==========================================
    
    
    /**  
     * Description: 从FTP服务器下载文件  
     * @param host FTP服务器hostname  
     * @param port FTP服务器端口  
     * @param username FTP登录账号  
     * @param password FTP登录密码  
     * @param remotePath FTP服务器上的相对路径  
     * @param fileName 要下载的文件名  
     * @param localPath 下载后保存到本地的路径  
     * @return  
     */    
    public static boolean downloadFile(String host, int port, String username, String password, String remotePath,  
            String fileName, String localPath) {  
        boolean result = false;  
        FTPClient ftp = new FTPClient();  
        try {  
            int reply;  
            ftp.connect(host, port);  
            // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器  
            ftp.login(username, password);// 登录  
            reply = ftp.getReplyCode();  
            if (!FTPReply.isPositiveCompletion(reply)) {  
                ftp.disconnect();  
                return result;  
            }  
            ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录  
            FTPFile[] fs = ftp.listFiles();  
            for (FTPFile ff : fs) {  
                if (ff.getName().equals(fileName)) {  
                    File localFile = new File(localPath + "/" + ff.getName());  
  
                    OutputStream is = new FileOutputStream(localFile);  
                    ftp.retrieveFile(ff.getName(), is);  
                    is.close();  
                }  
            }  
  
            ftp.logout();  
            result = true;  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (ftp.isConnected()) {  
                try {  
                    ftp.disconnect();  
                } catch (IOException ioe) {  
                }  
            }  
        }  
        return result;  
    }  
}


springMVC的使用:

   
    @Autowired
    private FtpConfig ftpConfig;

    @RequestMapping("/uploadFiles")
    @ResponseBody
 public MSG uploadFiles(@RequestParam("albumId")Integer albumId,@RequestParam("file")MultipartFile[] files) throws IOException {

        List<Photo> photoList = new ArrayList<Photo>();

        //循环上传多个图片
        for(MultipartFile file:files){
            Photo photo = new Photo();

            String oldName = file.getOriginalFilename();
            String picNewName = UploadUtils.generateRandonFileName(oldName);//通过工具类产生新图片名称,防止重名

            String picSavePath = UploadUtils.generateRandomDir(picNewName);//通过工具类把图片目录分级

            photo.setPhotoUrl(picSavePath+"/"+picNewName);//设置图片的url--》就是存储到数据库的字符串url
            photo.setAlbumId(albumId);//设置图片所属相册id
            photo.setPhotoDesc(oldName);//设置图片描述

            photoList.add(photo);

            FtpUtil.pictureUploadByConfig(ftpConfig,picNewName,picSavePath,file.getInputStream());//上传到图片服务器的操作
        }

        //添加到数据库
        iPhotoService.savePhotoList(photoList);//调用service层方法

        return MSG.success();//上传成功做的操作,我这里返回上传成功的信号
    }

UploadUtils.java工具类:

public class UploadUtils {
	
	/**
	 * 得到真实文件名
	 * @param fileName
	 * @return
	 */
    public static String subFileName(String fileName){
        //查找最后一个 \ (文件分隔符)位置
        int index = fileName.lastIndexOf(File.separator);
        if(index == -1){
            //没有分隔符,说明是真实名称
            return fileName;
        }else {
            return fileName.substring(index+1);
        }
    }

    /**
     * 获得随机UUID文件名
     * @param fileName
     * @return
     */
    public static String generateRandonFileName(String fileName){
        //首相获得扩展名,然后生成一个UUID码作为名称,然后加上扩展名
        String ext = fileName.substring(fileName.lastIndexOf("."));
        return UUID.randomUUID().toString()+ext;
    }

    /**
     * 获得hashcode 生成二级目录
     * @param uuidFileName
     * @return
     */
    public static String generateRandomDir(String uuidFileName){
        int hashCode = uuidFileName.hashCode();//得到它的hashcode编码
        //一级目录
        int d1 = hashCode & 0xf;
        //二级目录
        int d2 = (hashCode >> 4) & 0xf;
        return "/"+d1+"/"+d2;
    }
}

最后亲测能够实现上传。

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐