使用spring6完成文件上传

在Spring 6中,使用基于Servlet标准的 MultipartResolver确保了更好的兼容性和性能,同时减少了对外部库的依赖。

MultipartResolver是一个接口,定义了解析multipart请求(包括文件上传)的策略。Spring提供了多种实现,包括基于Servlet容器的实现和过去常用的基于Apache Commons FileUpload的实现。

主要实现

StandardServletMultipartResolver

CommonsMultipartResolver (spring6中不再使用)

具体代码实现如下:

import jakarta.servlet.Filter;
import jakarta.servlet.MultipartConfigElement;
import jakarta.servlet.ServletRegistration;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebAppInitializer  extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMVCConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    // 配置过滤器
    protected Filter[] getServletFilters() {
        // 配置字符编码过滤器
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceResponseEncoding(true);
        characterEncodingFilter.setForceRequestEncoding(true);
        // 配置HiddenHttpMethodFilter
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
    }
    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        //设置允许上传的单个文件大小为
        long  maxFileSize = 500*1024*1024;
        //设置允许上传的总文件大小2000M
        long maxRequestSize = 2000*1024*1024;
        //设置文件上传阀值
        int fileSizeThreshold = 0;
        registration.setMultipartConfig(new MultipartConfigElement(null,maxFileSize,maxRequestSize,fileSizeThreshold));
    }
}

SpringMVC配置类:

@Configuration
@ComponentScan("com.ssm.controller")
@EnableWebMvc
public class SpringMVCConfig  implements  WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
        registry.addResourceHandler("/upload/**").addResourceLocations("/upload/");
    }

     //文件上传的时候要添加这个类的实例处理表单
    @Bean
    public MultipartResolver multipartResolver() {
        //创建一个
        StandardServletMultipartResolver multipartResolver =
                new StandardServletMultipartResolver();
        //返回
        return multipartResolver;
    }}

@Controller
public class UserController {
    @Autowired
    private UserService  userService;
    @RequestMapping("/users")
    @ResponseBody
    public  Result  findAll(){
        List<User> all = userService.findAll();
        return  new Result(200,all);
    }

    @RequestMapping(value = "/update",method = RequestMethod.POST)
    @ResponseBody
    public Result updateUser(HttpServletRequest request,
                            User user,
                             @RequestParam("file") MultipartFile multipartFile){

        //处理用户数据
    /*    User user = new User();
        user.setId(id);
        user.setUserName(userName);
        user.setRealName(realName);
        user.setTel(tel);
        user.setGender(gender);
        user.setRegisterTime(registerTime);
        user.setLastLoginTime(lastLoginTime);
        System.out.println(user);
*/
        System.out.println("user:"+user);
        System.out.println(multipartFile.getOriginalFilename());
        // 获取请求参数的名字
        String name = multipartFile.getName();
        System.out.println(name); //fileName

        // 获取的是文件真实的名字
        String originalFilename = multipartFile.getOriginalFilename();
        System.out.println(originalFilename); //touxiang.jpeg

        InputStream in = null; // 输入流,负责读客户端的文件
        File destFile=null;
        try {
            in = multipartFile.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(in); // 封装成带有缓冲区的输入流
            // 输出流
            ServletContext application = request.getServletContext();
            String realPath = application.getRealPath("/upload");
            File file = new File(realPath);
            if(!file.exists()){
                file.mkdirs();
            }
            destFile = new File(file.getAbsolutePath()  ,"tx"+ originalFilename.substring(originalFilename.lastIndexOf(".")));
            multipartFile.transferTo(destFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //保存到数据库
        user.setImgUrl("/upload/"+destFile.getName());
        userService.update(user);
        return new Result(200,"/upload/"+destFile.getName(),"上传成功");
    }

    @RequestMapping("/users/{id}")
    @ResponseBody
    public  Result  findById(@PathVariable("id") Integer id){
        User user = userService.findById(id);
        return  new Result(200,user);
    }


}

前端页面:

<template>
    <div>
        <div class="container" style="overflow: scroll;">
            <div class="handle-box">
                <el-row class="top-btn">
                    <el-col :span="12">
                        <el-button type="success" @click="isEdit != isEdit">点击修改</el-button>
                        <el-button @click="rollback" style="color:#1C84C6">返回</el-button>
                    </el-col>
                    <!-- <el-col :span="12">
                        <el-input class="handle-input" placeholder="请输入要查询的日志关键字">
                            <template #append>
                                <el-button :icon="Search" />
                            </template>
                        </el-input>
                    </el-col> -->
                </el-row>
            </div>
            <el-divider></el-divider>
            <el-form  :model="userForm" label-width="auto" style="max-width: 600px;">
                   <el-form-item label="点击修改头像">
                       <el-upload ref="chargeFormRef" 
                            class="avatar-uploader" 
                            :show-file-list="false"
                            :auto-upload="false"
                            :on-change="handleChange" 
                          >
                           <!-- <img v-if="chargeForm.imageUrl" :src="chargeForm.imageUrl" class="avatar" /> -->
                           <el-avatar v-if="chargeForm.imageUrl" :src="chargeForm.imageUrl" class="avatar" />
                           <el-icon v-else class="avatar-uploader-icon">
                               <Plus />
                           </el-icon>
                       </el-upload>
                    </el-form-item>
                    <el-form-item label="用户名">
                    <el-input v-model="userForm.userName" />
                    </el-form-item> 
                    <el-form-item label="真实姓名">
                    <el-input v-model="userForm.realName" />
                    </el-form-item> 
                    <el-form-item label="手机号">
                         <el-input v-model="userForm.tel" />
                    </el-form-item> 
                    <el-form-item label="手机号">
                        <el-radio-group v-model="userForm.gender">
                            <el-radio value="男" label="男">男</el-radio>
                            <el-radio value="男" label="女">女</el-radio>
                        </el-radio-group>
                    </el-form-item> 
                    <el-form-item label="注册时间">
                       <el-input v-model="userForm.registerTime"  disabled />
                    </el-form-item> 
                    <el-form-item label="上次登录时间" disabled>
                       <el-input v-model="userForm.lastLoginTime"   disabled/>
                    </el-form-item> 
                        <el-form-item>
                    <el-button type="primary" @click="save">保存</el-button>
                    <el-button>取消</el-button>
                    </el-form-item>
                </el-form>
        </div>
       
    </div>
</template>

<script setup>
import { ref, reactive, toRefs,onMounted } from 'vue'
import { Search,Plus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { reqUpload,saveUser } from '../api/upload'
/*******返回****** */
/**上传图片组件的显示 */
const props = defineProps({
    flag: String
})
const { flag } = toRefs(props)
const emit = defineEmits(['update:flag'])
const rollback = () => {
    emit('update:flag', '1')
}
const isEdit = ref(false)

//信息的收集
let chargeForm = reactive({
    imageUrl: '/api/upload/tx.jpg',
})
const chargeFormRef = ref()
const userForm = reactive({
    id:2,
    userName:'超级管理员',
    realName:'张老师',
    tel:'136123456789',
    gender:'男',
    registerTime:'2024-12-11',
    lastLoginTime:'2024-12-01',
    file:null
})
const  save = ()=>{
    //调用后端接口保存用修改之后的信息
    saveUser(userForm).then(res=>{
        chargeForm.imageUrl ='/api/'+ res.data.data
    })
}

const handleChange= (uploadFile)=>{
    //选中图片的回显
    chargeForm.imageUrl= URL.createObjectURL(uploadFile.raw)
   userForm.file=uploadFile.raw
}

onMounted(()=>{
    // 页面挂在完成 根据id 查询用户信息 当前小案例中没有做
    
})
</script >
<style lang="less" scoped>
.avatar-uploader .avatar {
    width: 178px;
    height: 178px;
    display: block;
}

.handle-box {
    margin-bottom: 20px;
}


.handle-input {
    float: right;
    width: 240px;
}

.table {
    width: 100%;
    font-size: 14px;
}

.red {
    color: #F56C6C;
}

.blue {
    color: #1296e2;
    font-weight: bold;
}

.mr10 {
    margin-right: 10px;
}

.table-td-thumb {
    display: block;
    margin: auto;
    width: 40px;
    height: 40px;
}

.cell {
    display: inline-block;

    .el-button {
        margin-left: 0px;
    }
}

.right-btn {
    justify-content: center;

    .el-button {
        margin-right: 6px;
        padding: 1px 5px;
    }
}

.form-demo {
    .el-input {
        width: 60%;
    }

    .el-input-number {
        width: 60%;
    }

}

.handle-input .el-input-group__append button.el-button,
.el-input-group__append button.el-button:hover {
    background-color: #1C84C6;
    color: #fff;
    font-weight: 700;
}
</style>

<style>
.avatar-uploader .el-upload {
    border: 1px dashed var(--el-border-color);
    /* border-radius: 6px; */
    border-radius: 150px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
    
}

.el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
}
</style>

axios请求:

export const saveUser = (data) => {
  // 创建了一个新的 FormData 对象,用于构建表单数据,并将file添加到FormData对象中
  const formData = new FormData();
     for (const key in data) {
        if (data.hasOwnProperty(key)) {
          const value = data[key];
          // 注意:文本、数字可以直接添加,文件则需要用append添加
          formData.append(key, value);
        }
      }
    console.log(formData)   
  return request({
        url:`/update`,
        method:'post',
        data:formData,
    })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值