教你生成的zip如何直传到oss

148 阅读3分钟

1. 背景

最近在做项目的时候有一个需求就是将生成的zip直接上传到oss中。查了很多资料以后发现普遍都是将zip先放在本地目录,然后再上传到oss中。这样其实有一个问题就是你生成的zip要么自己每次手动清理,要么就是上传到oss以后再用代码清理掉存放在本地的zip。

那么怎么直接上传到oss呢?本篇将告诉你无需本地存储。直接将生成的zip上传到oss中。返回下载链接给前端。让前端自己下载。

2. 步骤分析

那么我们要拆分一下我们要干嘛?

  1. 组装zip文件中的每一个文件
  2. 将每个文件放进zip中
  3. 将zip上传到oss

3. 实现

3.1. 生成zip文件

    /**
     * 创建json的zip文件
     *
     * @param listMap 数据集
     * @return oss路径
     */
    public static String createJsonFile(Map<String, List<I18nDTO>> listMap) {
        ByteArrayOutputStream zipos = new ByteArrayOutputStream(61858764);//设置大小为60M
        ZipOutputStream zos = new ZipOutputStream(zipos);//创建压缩流,初始化一个输出流缓存区


        // 创建多个ByteArrayInputStream作为示例
        listMap.forEach((key, value) -> {
            try {
                JSONObject jsonObject = new JSONObject();
                ByteArrayOutputStream os = new ByteArrayOutputStream(61858764);//设置大小为60M
                for (I18nDTO i18nDTO : value) {
                    jsonObject.put(i18nDTO.getFieldsCode(), i18nDTO.getLanguageValue());
                }
                //创建一个压缩文件里的名称
                ZipEntry zipEntry = new ZipEntry(key + ".json");
                String s = JsonFormatTool.formatJson(jsonObject.toString());
                os.write(s.getBytes());
                zos.putNextEntry(zipEntry);
                os.writeTo(zos);
                zos.closeEntry();
                os.close();
            } catch (IOException e) {

            }

        });

        try {
            zos.close();//注意关闭流的顺序,在上传oss之前必须关闭流否则下载解压的时候会报“文件末端错误”的问题
            zipos.close();
            ByteArrayInputStream zipis = new ByteArrayInputStream(zipos.toByteArray());
            zipis.close();
        } catch (IOException e) {
        }

        ByteArrayInputStream zipis = new ByteArrayInputStream(zipos.toByteArray());
        // 关闭ZipInputStream
        String filePath = IdUtils.fastSimpleUUID() + ".zip";
        CreateFileUtil.ossUploadByStream(filePath, zipis);

        return filePath;
    }

3.2. JsonFormatTool 工具

public class JsonFormatTool {
    /**
     * 单位缩进字符串。
     */
    private static String SPACE = "   ";

    /**
     * 返回格式化JSON字符串。
     *
     * @param json 未格式化的JSON字符串。
     * @return 格式化的JSON字符串。
     */
    public static String formatJson(String json) {
        StringBuilder result = new StringBuilder();

        int length = json.length();
        int number = 0;
        char key = 0;

        // 遍历输入字符串。
        for (int i = 0; i < length; i++) {
            // 1、获取当前字符。
            key = json.charAt(i);

            // 2、如果当前字符是前方括号、前花括号做如下处理:
            if ((key == '[') || (key == '{')) {
                // (1)如果前面还有字符,并且字符为“:”,打印:换行和缩进字符字符串。
                if ((i - 1 > 0) && (json.charAt(i - 1) == ':')) {
                    result.append('\n');
                    result.append(indent(number));
                }

                // (2)打印:当前字符。
                result.append(key);

                // (3)前方括号、前花括号,的后面必须换行。打印:换行。
                result.append('\n');

                // (4)每出现一次前方括号、前花括号;缩进次数增加一次。打印:新行缩进。
                number++;
                result.append(indent(number));

                // (5)进行下一次循环。
                continue;
            }

            // 3、如果当前字符是后方括号、后花括号做如下处理:
            if ((key == ']') || (key == '}')) {
                // (1)后方括号、后花括号,的前面必须换行。打印:换行。
                result.append('\n');

                // (2)每出现一次后方括号、后花括号;缩进次数减少一次。打印:缩进。
                number--;
                result.append(indent(number));

                // (3)打印:当前字符。
                result.append(key);

                // (4)如果当前字符后面还有字符,并且字符不为“,”,打印:换行。
                if (((i + 1) < length) && (json.charAt(i + 1) != ',')) {
                    result.append('\n');
                }

                // (5)继续下一次循环。
                continue;
            }

            // 4、如果当前字符是逗号。逗号后面换行,并缩进,不改变缩进次数。
            if ((key == ',')) {
                result.append(key);
                result.append('\n');
                result.append(indent(number));
                continue;
            }

            // 5、打印:当前字符。
            result.append(key);
        }

        return result.toString();
    }

    /**
     * 返回指定次数的缩进字符串。每一次缩进三个空格,即SPACE。
     *
     * @param number 缩进次数。
     * @return 指定缩进次数的字符串。
     */
    private static String indent(int number) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < number; i++) {
            result.append(SPACE);
        }
        return result.toString();
    }
}

3.3. 阿里云oss上传

public static void ossUploadByStream(String filePath, InputStream input) {
        OSS ossClient = new OSSClientBuilder().build(AliYunConstant.endpoint, AliYunConstant.accessKeyId, AliYunConstant.accessKeySecret);
        PutObjectRequest putObjectRequest = new PutObjectRequest(AliYunConstant.bucketName, filePath, input);
        ossClient.putObject(putObjectRequest);
        ossClient.shutdown();
    }

阿里云sdk依赖

<dependency>
  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-sdk-oss</artifactId>
  <version>3.8.0</version>
</dependency>