Window下为Typora搭建图片服务器(version 0.9.98)

原文链接

一、准备工作

服务器一台、安装nginx.
下载Typora。Typora官网
Typora插件

二、准备上传接口(java实现)

application.yml

# 应用名称
spring:
  application:
    name: typora-upload
  servlet:
    multipart:
      max-file-size: 1MB
      max-request-size: 1MB
      enabled: true
server:
  port: 8800


upload:
  image:
    valid:
      suffixes: .png           #图片格式,多种类型可以,分割。这里只用做截图使用png

fingerling:
  upload:
    image:
      context:
        path: /img     #图片目录   对应nginx下img文件夹 
      base:
        path: /www/server/nginx/html/img    #图片保存路径
      online:
        path: https://xxx          #服务器地址
      key: xxxxxxxxxxx           #key和secret自定义防止接口破坏
      secret: xxxxxxxxxxxxxx

pom.xml

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.directory.studio/org.apache.commons.io -->
        <dependency>
            <groupId>org.apache.directory.studio</groupId>
            <artifactId>org.apache.commons.io</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

@RestController
public class UploadController {
    public static final Logger logger = LoggerFactory.getLogger(UploadController.class);
    final
    UploadUtil uploadUtil;

    @Value("${fingerling.upload.image.key}")
    private String key;


    @Value("${fingerling.upload.image.secret}")
    private String secret;


    public UploadController(UploadUtil uploadUtil) {
        this.uploadUtil = uploadUtil;
    }

    @PostMapping("/upload")
    public ResultBean uploadFile(@RequestParam("fileData")String fileData, @RequestHeader String key, @RequestHeader String secret){
        if(key == null && secret == null){
            return new ResultBean(01,"非法请求",null);
        }else if(!key.equals(key) && !secret.equals(secret)){
            return new ResultBean(02,"令牌鉴权失败",null);
        }
        logger.info("request:{}",fileData);
        String img = null;
        MultipartFile file = uploadUtil.base64ToMultipart(fileData);
        try {
            img = uploadUtil.upload(file);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultBean(03,"上传失败",null);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("url",img);
        return new ResultBean(0,"成功",jsonObject);
    }


}

@Component
public class UploadUtil {


    @Value("${fingerling.upload.image.base.path}")
    private String uploadPath;

    @Value("${fingerling.upload.image.context.path}")
    private String contextPath;

    @Value("${fingerling.upload.image.online.path}")
    private String onlinePath;

    @Value("${upload.image.valid.suffixes}")
    private String validSuffix;

    public static final Logger logger = LoggerFactory.getLogger(UploadUtil.class);


    public String upload(MultipartFile file) throws IOException {

        //获取文件名称;
        String name = file.getOriginalFilename();

        //获取当前时间作为最终存储文件的上级目录;
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String today = format.format(new Date());

        //保存的文件名:UUID+文件后缀;
        String fileName = UUID.randomUUID().toString()+ getFileSuffix(name);
        //文件类型校验;
        String type = getFileSuffix(name);
        logger.info("文件类型:{}",type);
        if (!validSuffix.contains(type)) {
            logger.error("UploadFile failed for suffix error;error sufiix:" + type);
            throw new IOException("M2-000001");
        }

        //文件最终上传地址;
        String uploadFolder = uploadPath + File.separator + today;

        //上传文件;
        File dir = new File(uploadFolder);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String targetUploadPath = dir + File.separator + fileName;
        String targetContextPath = contextPath + File.separator + today + File.separator + fileName;
        try {
            FileUtils.writeByteArrayToFile(new File(targetUploadPath), file.getBytes());
        } catch (IOException e) {
            logger.error("UploadFile failed", e);
            throw new IOException("M2-000002");
        }
        //返回文件存储位置;
        return onlinePath+targetContextPath;
    }

    public static String getFileSuffix(String name) {
        return name.substring(name.lastIndexOf("."), name.length());
    }


    public  MultipartFile base64ToMultipart(String base64) {
        try {
            String[] baseStrs = base64.split(",");

            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = new byte[0];
            b = decoder.decodeBuffer(baseStrs[1]);

            for(int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }

            return new Base64DecodeMultipartFile(b, baseStrs[0]);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

public class Base64DecodeMultipartFile implements MultipartFile {
    private final byte[] imgContent;
    private final String header;

    public Base64DecodeMultipartFile(byte[] imgContent, String header) {
        this.imgContent = imgContent;
        this.header = header.split(";")[0];
    }

    @Override
    public String getName() {
        return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
    }

    @Override
    public String getOriginalFilename() {
        return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];
    }

    @Override
    public String getContentType() {
        return header.split(":")[1];
    }

    @Override
    public boolean isEmpty() {
        return imgContent == null || imgContent.length == 0;
    }

    @Override
    public long getSize() {
        return imgContent.length;
    }

    @Override
    public byte[] getBytes() throws IOException {
        return imgContent;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(imgContent);
    }

    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        new FileOutputStream(dest).write(imgContent);
    }

}

三、配置Typora插件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I4a0lscc-1612377823986)(https://blog.lihaijian.top/upload/2021/02/image-71a93917cb2442e0aa6920193cb264bf.png)]
将plugins文件夹和window.html移动到
image.png

配置plugins文件夹下的upload.js

文件最后设置上传路径和请求头
image.png
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GSvtrevY-1612377823992)(https://blog.lihaijian.top/upload/2021/02/image-403654f322f04d4d8370a2b1f4219964.png)]

四、重启Typora

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CuNUcZB4-1612377823994)(https://blog.lihaijian.top/upload/2021/02/image-b9f6747e8ac24ccda10895d07403a817.png)]

问题:该版本会出现重复上传和导致偏好设置打不开问题。
解决方案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值