FTP资源服务器如何使用

目录

搭建FTP服务器

实现效果

具体实现

流程思想

注意细节

数据库设计

 前端实现

后端实现


搭建FTP服务器

搭建FTP资源服务器_江河的笑的博客-CSDN博客

实现效果

前端实现页面如下

图片上传到ftp服务器files根目录下,当前我未上传 (其他文件夹可以忽视,这是我以前传的)

点击上传,并上传到服务器,页面如下

 此时咱们再查看FTT文件服务器

 文件已经加入进去了

具体实现

流程思想

前端显示的图片是遍历数据库中的存储在ftp服务器上的图片地址

当我上传图片:第一是把图片真上传到ftp服务器上,第二是把图片地址存储到数据库中

注意细节

1、我的域名进行了域名解析,也就是123.123.444.554变成了jinruixiang.top,你们如果没解析需要相应进行修改

2、图片类别传参你们可以去掉,token参数也可去掉。想了解token就去Shiro权限管理的博客,利用有上传好的代码,注释详尽

基于Shiro+Springboot+Mybatis+Vue权限管理系统_江河的笑的博客-CSDN博客

数据库设计

ftp_img

ftp_img_type 

 

 前端实现

ImgManage,这是我自定义的一个组件

<template>
  <div style="width: 100%">
    <div class="img_list">
      <div v-for="(item, index) in imgList" :key="index">
        <img :src="item.imgUrl" alt="" />
        <el-button
          class="del"
          @click="delImg(item)"
          size="mini"
          type="primary"
          plain
          >删除</el-button
        >
      </div>
    </div>
    <el-upload
      class="upload-demo"
      action="api/img/upload"
      drag
      multiple
      :auto-upload="false"
      :data="{ typeId: cTypeId }"
      ref="upload"
      :on-success="handleAvatarSuccess"
      :headers="{
        token:token
      }"
    >
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <div class="el-upload__tip" slot="tip">
        只能上传jpg/png文件,且不超过500kb
      </div>
    </el-upload>
    <el-button
      style="margin-left: 10px"
      size="small"
      type="success"
      @click="submitUpload"
      >上传到服务器</el-button
    >
  </div>
</template>

<script>
export default {
  data() {
    return {
      imgList: [],
      token: this.getToken(),
      dialogImageUrl: "",
      dialogVisible: false,
      disabled: false,
    };
  
  },
props:{
  cTypeId:{
    type:Number,
    default:4
  }
},

  methods: {
    showMsg(result) {
      if (result.status === 200) {
        const data = result.data;
        if (data.status === 200) {
          this.$message({
            showClose: true,
            message: data.msg,
            type: "success",
            duration: "600",
          });
        } else {
          this.$message({
            showClose: true,
            message: data.msg,
            type: "error",
            duration: "3000",
          });
        }
      } else {
        this.$message({
          showClose: true,
          message: "操作失败,请联系管理员",
          type: "error",
          duration: "3000",
        });
      }
    },
    getImg() {
      this.$API.manage
        .getImg(this.cTypeId, this.token)
        .then((res) => {
          if (res.data.status !== 200) {
            this.showMsg(res);
          } else {
            this.imgList = res.data.list;
          }
        });
    },
    submitUpload() {
      this.$refs.upload.submit();
    },
    delImg(item) {
      this.$API.manage.delImg(item.imgId, this.token).then((res) => {
        this.showMsg(res);
        if (res.data.status == 200) {
          this.getImg();
        }
      });
    },

    handleAvatarSuccess(res, file) {
      this.getImg();
    },
  },
  mounted() {
    this.getImg();
  },
};
</script>

<style lang="less" scoped>
.img_list {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  div {
    width: 23%;
    height: auto;
    margin: 1%;
    position: relative;
    .del {
      position: absolute;
      right: -1px;
      top: -1px;
    }
    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>

config/index.js跨域处理,只加了proxyTable

'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.

const path = require('path')

module.exports = {
  dev: {
    changeOrigin: true,
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    //  assetsPublicPath: './',
    proxyTable: {
      '/api': {
        target: 'http://127.0.0.1:9000',
        pathRewrite: {
          '^/api': ''
        }
      }
      
    },


    // Various Dev Server settings
    host: 'localhost', // can be overwritten by process.env.HOST
    port: 80, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
    autoOpenBrowser: false,
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-

    
    /**
     * Source Maps
     */

    // https://webpack.js.org/configuration/devtool/#development
    devtool: 'cheap-module-eval-source-map',

    // If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
    cacheBusting: true,

    cssSourceMap: true
  },

  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    // assetsPublicPath: '/',
    assetsPublicPath: './',


    /**
     * Source Maps
     */

    productionSourceMap: true,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map',

    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],

    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

axios请求文件

const delImg=(imgId,token)=>{
    return axios.delete("api/manage/deleteImg",{
        params:{
            imgId:imgId
        },
        headers: {
            token: token
        }
    })
}

ImgManage组件调用,我这里传入的是图片类别参数,你们可以不设置,但是相应传参可以去掉

<template>
  <div>
    <img-manage :cTypeId="$constant.IMG_TYPE.IMG_JIN_GUN"/>
  </div>
</template>

<script>
import ImgManage from '@/components/imgManage/ImgManage'
export default {
  components: { ImgManage },

}
</script>

<style>

</style>

后端实现

自己建一个utils包,放入ftpUtil.java

package com.carve.carvesystem.utils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

public class FtpUtil {

    //    ftp服务器ip地址
    private static final String FTP_ADDRESS = "xxxx.xxxx.xxx.xxx";

    private static final int FTP_PORT = 21;
    private static final String FTP_USERNAME = "user-file";
    private static final String FTP_PASSWORD = "123";

    //    路径
    private static final String FTP_BASEPATH = "/home/user-file/files";

    //    存储路径
    private static final String SAVE_BASEPATH = "http://jinruixiang.top/files/";

    public static String uploadFile(MultipartFile file) throws IOException {

        //获取上传的文件流

        InputStream inputStream = file.getInputStream();

//        获取上传的文件名
        String fileName = file.getOriginalFilename();
//        截取后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));

//        使用UUID拼接后缀,定义一个不重复的文件名
        String finalName = UUID.randomUUID() + suffix;


        FTPClient ftp = new FTPClient();


        try {
            int reply;
            ftp.connect(FTP_ADDRESS, FTP_PORT);
            ftp.login(FTP_USERNAME, FTP_PASSWORD);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return null;
            }

            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.makeDirectory(FTP_BASEPATH);
            ftp.changeWorkingDirectory(FTP_BASEPATH);
            ftp.enterLocalPassiveMode();
            ftp.storeFile(finalName, inputStream);
            inputStream.close();
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return SAVE_BASEPATH + finalName;


    }
}

controller层的FileController调用

package com.carve.carvesystem.controller;


import com.carve.carvesystem.service.ImgService;
import com.carve.carvesystem.utils.FtpUtil;
import io.swagger.annotations.Api;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;


import java.io.IOException;



@Api(value = "文件上传,下载相关功能")
@RestController
@RequestMapping("/img")
public class FileController {

    @Autowired
    private ImgService imgService;
    // 文件上传 (可以多文件上传)
    @RequiresPermissions({"save"})
    @PostMapping("upload")
    public String fileUploads(@RequestHeader("token") String token,Integer typeId, @RequestParam("file") MultipartFile file) throws IOException {



//        调用自定义的FTP工具类上传文件
        String fileUrl= FtpUtil.uploadFile(file);

        if(!StringUtils.isEmpty(fileUrl)){
            imgService.addImg(typeId,fileUrl);
//        设置对象中的图片名
//            user.setPicPath(fileName)
//            添加用户到数据库
//            userService.addUser(user);
        }

        return fileUrl;

    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江河地笑

实践是检验真理的唯一标准

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值