如何优雅的将 图片文字上传至服务器?

Posted 张子行的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优雅的将 图片文字上传至服务器?相关的知识,希望对你有一定的参考价值。

本文目录

前言

可能很多小伙伴们在学习 JAVA WEB 的时候,都或多或少的接触过 IO 流等相关方面的知识,从最简单的在 JAVA 环境下实现文件的复制拷贝,然后进阶到WEB环境的文件传输、拷贝、存储。最后高级点到整合第三方存储服务来实现,甚至还有将文件存储在数据库的(不推荐)。本文的目的在于向大家介绍,实战中是如何实现这个需求的

需求分析

下图是我从若依管理系统截取的一张图片,可以看到这个界面需要将公告标题、公告内容(为了突出本文要点,公告内容只能是图片)、公告类型存储到数据库中。提交参数有文字、图片,如果是你会怎么开发这个接口呢?

  1. 文字内容好办,实体类封装相关字段,然后操作数据库进行数据插入即可,图片也好办,存到服务器或者外接第三方存储服务,然后将返回的 IMG 的地址存到数据库中即可
  2. 问题一:后端接口如何同时接收图片、文字
  3. 问题二:如果是将文件存储到服务器内,绝对路劲 or 相对路劲?傻傻分不清楚。如果是外接第三方存储服务则不必操心这个问题

下文将针对如上俩个问题展开论述~

@RequestPart 解决问题一

当前请求如果请求头中包含 multipart/form-data ,@RequestPart 会自动将接收到的 JSON 字符串封装成一个对象接收

指定 JSON 字符串的传输形式为 application/json

后端接收方式

@Slf4j
@RestController
@RequestMapping
public class FileController 
    @PostMapping(value = "/uploadFile")
    public R uploadFile(@RequestPart("user") User user,
                        @RequestPart("assignPath") String assignPath,
                        @RequestPart("file") MultipartFile file) 
        try 
            String path = FileUploadUtils.uploadFile(null, file, assignPath);
            user.setImg(path);
            System.err.println(user.toString());
            //模拟数据入库操作
            boolean update = true;
            if (update) return R.ok(path);
            //数据入库失败应删除文件资源,避免造成服务器压力过大问题
            FileUploadUtils.deleteFile("更新成功:" + path);
            return R.failed("更新失败");
         catch (Exception e) 
            e.printStackTrace();
            log.error(e.getMessage());
            return R.failed("内部服务器错误");
        
    


@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
class User implements Serializable 
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private String img;
    private String name;
    private String age;

ResourceUtils 解决问题二

ResourceUtils 是 Spring 为我们提供的一个工具类,可以通过它可以获取项目类路劲下的文件,通过这些文件继而可以定位到文件的绝对路劲,删除文件调用 new File(url).delete() 即可。下面是我写的一个工具类

@Slf4j
public class FileUploadUtils 

    public static String getFileType(String fileName) 
        int separatorIndex = fileName.lastIndexOf(".");
        if (separatorIndex < 0) 
            return "";
        
        return fileName.substring(separatorIndex + 1).toLowerCase();
    

    /**
     * @param serverName 服务名(网关中配置的服务名,服务没走网关传null即可)
     * @param file       要保存的文件
     * @param targetPath 指定存储路劲(默认保存项目的/static/file路劲下)
     * @return
     * @throws IOException
     */
    public static String uploadFile(String serverName, MultipartFile file, String targetPath) throws IOException 
        IdWorker idWorker = new IdWorker();
        String type = getFileType(file.getOriginalFilename());
        File path = new File(ResourceUtils.getURL("classpath:").getPath());
        if (!path.exists()) path = new File("");
        if (null == targetPath) targetPath = "/static/file";
        else targetPath = "/static/" + targetPath + "/";
        File upload = new File(path.getAbsolutePath(), targetPath);
        if (!upload.exists()) upload.mkdirs();
        String newFileName = idWorker.nextId() + "." + type;
        String url = "";
        if (serverName != null) url = "/" + serverName + targetPath + newFileName;
        else url = targetPath + newFileName;
        log.info(upload.getAbsolutePath() + File.separator + newFileName);
        FileUtils.copyInputStreamToFile(file.getInputStream(), new File(upload.getAbsolutePath() + File.separator + newFileName));
        return url;
    

    public static Boolean deleteFile(String url) throws IOException 
        File path = new File(ResourceUtils.getURL("classpath:").getPath());
        File file = new File(path.getAbsolutePath(), url);
        boolean delete = file.delete();
        return delete;
    


效果

数据可以成功入库、并且存储到服务器

如何限制上传文件的大小并返回优雅的提示?

首先在yml配置文件中添加如下配置,上传的文件超过我们配置的30MB,接口将会拒绝此次请求,会抛出异常

spring:
  servlet:
    multipart:
      enabled: true
#      单次请求大小不能超过30MB
      max-request-size: 30MB
#      多个文件总大小不能超过30MB
      max-file-size: 30MB

为了提高用户体验,我们最好补货一下这个异常,返回给用户:上传文件过大的提示

@Slf4j
@RestControllerAdvice
public class ExceptionApect 
    @ExceptionHandler(value = MultipartException.class)
    public @ResponseBody
    Result handleBusinessException(Exception ex) 
        String msg;
        if (ex instanceof MaxUploadSizeExceededException) 
            log.error(ex.getMessage());
            msg = "上传文件过大";
         else 
            msg = "上传文件失败";
        
        return Result.success(msg);
    


附录:多文件上传实现

@ApiOperation(value = "多文件上传", notes = "")
@PostMapping(value = "/uploadFiles")
public Result skillApplyFile(HttpServletRequest request) throws IOException 
    MultipartRequest multipartRequest = (MultipartRequest) request;
    String assignPath = request.getParameter("assignPath");
    Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
    Collection<MultipartFile> multipartFiles = fileMap.values();
    ArrayList<String> urls = new ArrayList<>();
    for (MultipartFile file : multipartFiles) 
        String url = FileUploadUtils.uploadFile(null, file, assignPath);
        urls.add(url);
    
    return Result.success(urls);

❥(_-)❥(-)❥(_-)❥(-)❥(_-)❥(-)❥(_-)❥(-)如果觉着本篇文章对你有帮助~可以点个赞哟❥(_-)❥(-)❥(_-)❥(-)❥(_-)❥(-)❥(^-)

以上是关于如何优雅的将 图片文字上传至服务器?的主要内容,如果未能解决你的问题,请参考以下文章

如何快速的将图片里的内容转换成文字

百度umeditor编辑器如何能实现直接粘贴把图片上传到服务器中?

简单的将图中文字转换到Word中的方法

java实现图片上传至服务器并显示,如何做?

java实现图片上传至服务器并显示,如何做?希望要具体的代码实现

Typora文章一键复制至博客