SpringBoot integra la carga de archivos OSS

1. Registre una cuenta en la nube de Alibaba y active el servicio OSS

1. Inicie sesión en la cuenta de Alibaba Cloud
imagen
2. Cree un depósito
imagen
3. Cree un subusuario
imagen
Asigne permisos a los usuarios y abra todos los permisos para operar OSS (también se puede cambiar según las necesidades comerciales)
imagen
4. Configure y cargue cruz -reglas de dominio

  • Cualquier fuente: *
  • Método permitido: POST
  • Cualquier encabezado de solicitud Encabezados: *

imagen

2. Método de carga de archivos

1. Método de transmisión directa del servidor

Todos los usuarios de OSS utilizarán el servicio de carga. El método de carga común en la web es que el usuario carga el archivo en el servidor de aplicaciones a través del navegador o la aplicación, y el servidor de aplicaciones luego carga el archivo en el OSS. En comparación con la carga directa de datos en el OSS, el método imagen
anterior tiene tres desventajas:

  • Carga lenta: los datos del usuario deben cargarse primero en el servidor de aplicaciones y luego cargarse en OSS. El tiempo de transmisión de la red es el doble que el de la transmisión directa a OSS. Si los datos no se transfieren a través del servidor de aplicaciones, sino que se transmiten directamente al OSS, la velocidad mejorará considerablemente. Además, OSS adopta el ancho de banda BGP, que puede garantizar la velocidad de transmisión entre varios operadores en varios lugares
  • Mala escalabilidad: si hay más usuarios posteriores, el servidor de aplicaciones se convertirá en un cuello de botella
  • Alto costo: es necesario preparar varios servidores de aplicaciones. Dado que el tráfico de carga de OSS es gratuito, si los datos se transmiten directamente a OSS sin pasar por el servidor de aplicaciones, se guardarán varios servidores de aplicaciones.

2. Después de la firma del lado del servidor, la transmisión directa del front-end

El servidor front-end web solicita una firma, y ​​luego el front-end (Vue) carga directamente, lo que no ejercerá presión sobre el servidor y es seguro y confiable.
Información relacionada: Descripción general de la carga directa de firmas del lado del servidor y configuración de devolución de llamada de carga

Ejemplo de conexión de Java: práctica de Java OSS
imagen

Subir proceso de devolución de llamada
imagen

  1. El front-end web solicita al servidor de aplicaciones que obtenga los parámetros necesarios para la carga (como accessKeyId de OSS, política, devolución de llamada y otros parámetros)
  2. El servidor de aplicaciones devuelve parámetros relacionados.
  3. El front-end web inicia directamente una solicitud de carga de archivos al servicio OSS
  4. Una vez completada la carga, el servicio OSS devolverá la llamada a la interfaz de devolución de llamada del servidor de aplicaciones.
  5. El servidor de aplicaciones devuelve una respuesta al servicio OSS
  6. El servicio OSS devuelve el contenido de la interfaz de devolución de llamada del servidor de aplicaciones al front-end web

3. SpringBoot integra OSS para realizar la carga de archivos

1. Agregue dependencias relacionadas en pom.xml

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

2. Modifique el archivo de configuración de SpringBoot
imagen

#操作oss需要的一些参数
aliyun:
  oss:
    accessKeyId: xxx # 阿里云的accessKeyId
    accessKeySecret: xxx    # accessKey 密码
    endPoint:  xxx # Endpoint:在阿里云oss控制台查看自己使用的endpoint,eg: oss-cn-shanghai.aliyuncs.com 
    bucketName: xxx   # bucket 名称
    policy:
      expire: 300 # 签名有效期(S)
    maxSize: 10 # 上传文件大小(M)
    callback: http://localhost:8080/aliyun/oss/callback # 文件上传成功后的回调地址
    dir:
      prefix: xxx/images/ # 上传文件夹路径前缀

3. Agregue la configuración Java relacionada con OSS
OSSClient utilizada para configurar el cliente de conexión OSS

/**
 * TODO 用于配置OSS的连接客户端OSSClient
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 19:04
 */
@Configuration
@Component
public class OssConfig {
    
    
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.accessKeyId}")
    private String ALIYUN_OSS_ACCESSKEYID;
    @Value("${aliyun.oss.accessKeySecret}")
    private String ALIYUN_OSS_ACCESSKEYSECRET;

    @Bean
    public OSSClient ossClient() {
    
    
        return new OSSClient(ALIYUN_OSS_ENDPOINT, ALIYUN_OSS_ACCESSKEYID, ALIYUN_OSS_ACCESSKEYSECRET);

    }
}

4. Encapsule la estrategia de carga de front-end para devolver los
parámetros de objeto necesarios para la carga directa de front-end

package org.pp.oss.model;

/**
 * TODO 获取OSS上传文件授权返回结果
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 19:07
 */
public class OssPolicyResult {
    
    
    private String accessKeyId;
//    @ApiModelProperty("用户表单上传的策略,经过base64编码过的字符串") 13
    private String policy;
//    @ApiModelProperty("对policy签名后的字符串") 15
    private String signature;
//    @ApiModelProperty("上传文件夹路径前缀") 17
    private String dir;
//    @ApiModelProperty("oss对外服务的访问域名") 19
    private String host;
//    @ApiModelProperty("上传成功后的回调设置")
    private String callback;
// 忽略getter、setter方法
}

5. Objeto de parámetro de devolución de llamada exitosa de carga de encapsulación
Cuando la carga OSS es exitosa, devolverá la llamada a la interfaz correspondiente de acuerdo con los parámetros de configuración

package org.pp.oss.model;

/**
 * TODO oss上传成功后的回调参数
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 19:10
 */
public class OssCallbackParam {
    
    
    //请求的回调地址
    private String callbackUrl;
    //回调是传入request中的参数
    private String callbackBody;
    //回调时传入参数的格式,比如表单提交形式
    private String callbackBodyType;


    public String getCallbackUrl() {
    
    
        return callbackUrl;
    }

    public void setCallbackUrl(String callbackUrl) {
    
    
        this.callbackUrl = callbackUrl;
    }

    public String getCallbackBody() {
    
    
        return callbackBody;
    }

    public void setCallbackBody(String callbackBody) {
    
    
        this.callbackBody = callbackBody;
    }

    public String getCallbackBodyType() {
    
    
        return callbackBodyType;
    }

    public void setCallbackBodyType(String callbackBodyType) {
    
    
        this.callbackBodyType = callbackBodyType;
    }
}

6. Encapsule el objeto de resultado de devolución de llamada después de que la carga sea exitosa.
El objeto de datos devuelto en la interfaz de devolución de llamada encapsula la información del archivo cargado.

/**
 * TODO oss上传文件的回调结果
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 19:14
 */
public class OssCallbackResult {
    
    
    private String filename;// 文件名称
    private String size;// 文件大小
    private String mimeType;// 文件的mimeType
    private String width;// 图片文件的宽
    private String height;// 图片文件的高
// 忽略getter、setter方法
}

7. Agregue la interfaz comercial OSS OssService

/**
 * TODO  oss上传管理Service
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 19:16
 */
public interface OssService {
    
    

    /**
     * oss上传策略生成
     * @return
     */
    OssPolicyResult policy();

    /**
     * oss上传成功回调
     * @param request
     * @return
     */
    OssCallbackResult callback(HttpServletRequest request);
}

8. Clase de implementación OssService

package org.pp.oss.service.impl;/*
package org.pp.oss.service.impl;

import org.pp.oss.model.OssCallbackResult;
import org.pp.oss.model.OssPolicyResult;
import org.pp.oss.service.OssService;

import javax.servlet.http.HttpServletRequest;

*/

import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.pp.oss.model.OssCallbackParam;
import org.pp.oss.model.OssCallbackResult;
import org.pp.oss.model.OssPolicyResult;
import org.pp.oss.service.OssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * TODO
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 19:17
 */
@Service
public class OssServiceImpl implements OssService {
    
    
    private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class);
    @Value("${aliyun.oss.policy.expire}")
    private int ALIYUN_OSS_EXPIRE;
    @Value("${aliyun.oss.maxSize}")
    private int ALIYUN_OSS_MAX_SIZE;
    @Value("${aliyun.oss.callback}")
    private String ALIYUN_OSS_CALLBACK;
    @Value("${aliyun.oss.bucketName}")
    private String ALIYUN_OSS_BUCKET_NAME;
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.dir.prefix}")
    private String ALIYUN_OSS_DIR_PREFIX;

    @Autowired
    private OSSClient ossClient;

    /**
     * 签名生成
     *
     * @return
     */
    @Override
    public OssPolicyResult policy() {
    
    
        OssPolicyResult result = new OssPolicyResult();
        // 存储目录
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String baseDir = ALIYUN_OSS_DIR_PREFIX + sdf.format(new Date());
        // 签名有效期
        long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
        Date expiration = new Date(expireEndTime);
        // 文件大小
        long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 *1024;
        // 回调地址
        OssCallbackParam callback = new OssCallbackParam();
        callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
        callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
        callback.setCallbackBody("application/x-www-form-urlencoded");
        // 提交节点
        String action = "https://" + ALIYUN_OSS_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
        try {
    
    
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE,0,maxSize);
            policyConds.addConditionItem(MatchMode.StartWith,PolicyConditions.COND_KEY, baseDir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("UTF-8"));
            // 返回结果
            result.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
            result.setPolicy(policy);
            result.setSignature(signature);
            result.setDir(baseDir);
            result.setCallback(callbackData);
            result.setHost(action);


        } catch (Exception e) {
    
    
            LOGGER.error("签名生成失败{e}", e);
        }

        return result;
    }

    @Override
    public OssCallbackResult callback(HttpServletRequest request) {
    
    
        OssCallbackResult result = new OssCallbackResult();
        String filename = request.getParameter("filename");
        filename = "http://".concat(ALIYUN_OSS_BUCKET_NAME).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
        result.setFilename(filename);
        result.setSize(request.getParameter("size"));
        result.setMimeType(request.getParameter("mimeType"));
        result.setHeight(request.getParameter("height"));
        result.setWidth(request.getParameter("width"));

        return result;
    }


}


9. Definir la interfaz OssController

package org.pp.oss.controller;

import cn.hutool.json.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.pp.oss.model.OssCallbackResult;
import org.pp.oss.model.OssPolicyResult;
import org.pp.oss.service.OssService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.CrossOrigin;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * TODO Oss相关操作接口
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/5/28 20:43
 */
@RestController
@RequestMapping("/aliyun/oss")
@CrossOrigin
public class AliyunOssController {
    
    

    @Autowired
    private OssService ossService;

    @CrossOrigin
    @RequestMapping("/policys")
    public Map<String,String> policysMap(){
    
    
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessId = "xxx";
        String accessKey = "xxx";
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-shanghai.aliyuncs.com";
        // 填写Bucket名称,例如examplebucket。
        String bucket = "xxx";
        // 填写Host地址,格式为https://bucketname.endpoint。
        String host = "https://" + bucket + "."+ endpoint;
        // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
        // String callbackUrl = "https://192.168.0.0:8888";
        // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String formatData = dateFormat.format(new Date());
        String dir = "osstest/"+formatData+ "/";

        // 创建ossClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
        try {
    
    
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("accessId", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            return respMap;
            // respMap.put("expire", formatISO8601Date(expiration));
            // 回调数据
//            JSONObject jasonCallback = new JSONObject();
//            jasonCallback.put("callbackUrl", callbackUrl);
//            jasonCallback.put("callbackBody",
//                    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
//            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
//            String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
//            respMap.put("callback", base64CallbackBody);
//
//            JSONObject ja1 = JSONObject.fromObject(respMap);
//            // System.out.println(ja1.toString());
//            response.setHeader("Access-Control-Allow-Origin", "*");
//            response.setHeader("Access-Control-Allow-Methods", "GET, POST");
//            response(request, response, ja1.toString());

        } catch (Exception e) {
    
    
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * oss上传签名生成
     * @return
     */
    @CrossOrigin
    @RequestMapping("/policy")
    public OssPolicyResult policy(){
    
    
        OssPolicyResult result = ossService.policy();
        System.out.println("result = " + result);
        return result;
    }

    /**
     * oss上传成功回调
     * @return
     */
    @RequestMapping("/callback")
    public OssCallbackResult callback(HttpServletRequest request){
    
    
        OssCallbackResult callback = ossService.callback(request);
        System.out.println("callback = " + callback);
        return callback;
    }


}

Pruebe la interfaz, como se muestra en la figura a continuación, la solicitud devuelve los parámetros correspondientes requeridos para cargar el archivo oss
imagen

4. Código de prueba de carga de archivos Vue

Para probar la interfaz de carga de archivos de manera más conveniente y rápida, elijo usar Vue+Element-Ui para crear un caso de carga simple 1. Crear un
proyecto Vue
Ingrese vue ui en la consola para iniciar la interfaz gráfica de administración del proyecto Vue
imagen
. http:/ /localhost:8000 , ingrese a la interfaz de operación como se muestra a continuación, lo que significa que el inicio se realizó correctamente
imagen
Busque el administrador del proyecto y cree un nuevo proyecto Vue
imagen

imagen

imagen

imagen

Aquí seleccione la versión de Vue2
imagen
y agregue las dependencias requeridas para este caso después de que la creación sea exitosa:

  • axios: se utiliza para iniciar solicitudes Ajax a servicios backend
  • element-ui: este caso usa Upload en la biblioteca de componentes ui para cargar archivos
    Habilite las dependencias correspondientes en main.js en el proyecto Vue
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from "axios";
import VueAxios from "vue-axios";
import router from './router'
import store from './store'

Vue.config.productionTip = false
// Vue.use(axios)
Vue.use(VueAxios,axios)
Vue.use(ElementUI);
new Vue({
    
    
  router,
  store,
  render: function (h) {
    
     return h(App) }
}).$mount('#app')

Cree el componente OssUpload, al que se puede hacer referencia en el proyecto

<template>
    <el-upload
        class="upload-demo"
        :action="objData.host"
        :before-upload="ossPolicy"
        :data="objData"
        :file-list="fileList"
        list-type="picture">
        <el-button size="small" type="primary">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
</template>

<script>
export default {
    
    
    data() {
    
    
        return {
    
    
            fileList: [],
            objData: {
    
    
                OSSAccessKeyId: '',
                policy: '',
                signature: '',
                key: '',
                host: '',
                dir: ''
            }

        };
    },
    methods: {
    
    
        ossPolicy(file) {
    
    
            let _self = this;
            // 在上传前  进行服务器签名
            return new Promise((resolve, reject) => {
    
    
                    this.axios.get("http://localhost:8080/aliyun/oss/policy")
                        .then(response => {
    
    
                            console.log(response)
                            _self.objData.OSSAccessKeyId = response.data.accessKeyId
                            _self.objData.policy = response.data.policy
                            _self.objData.signature = response.data.signature
                            _self.objData.dir = response.data.dir
                            _self.objData.host = response.data.host+''
                            _self.objData.key = response.data.dir + "${filename}"
                            resolve(true) // 继续上传
                        })
                        .catch(error => {
    
    
                            console.log(error)
                            reject(false)
                        })
                }
            )

        }
    }
}
</script>

<style>

</style>
在HelloWorld.vue中引用文件上传组件
```js
<template>
  <div class="hello">
    <h1>{
    
    {
    
     msg }}</h1>
    <OssUpload></OssUpload>
  </div>
</template>

<script>
// 引用组件
import OssUpload from "@/components/OssUpload.vue";
export default {
    
    

    name: 'HelloWorld',
    components: {
    
    OssUpload},
  props: {
    
    
    msg: String
  }
}
</script>
<style >

</style>

Depuración conjunta de front-end y back-end

  1. Inicie el servicio de back-end
    imagen

  2. Inicie el proyecto front-end
    imagen

Seleccione el archivo para cargar, como se muestra en la figura a continuación, significa que la carga se realizó correctamente
imagen
Verifique el OSSBucket correspondiente, la imagen se almacenó correctamente en el servicio OSS
imagen

dirección del proyecto

Supongo que te gusta

Origin blog.csdn.net/weixin_45688141/article/details/130969140
Recomendado
Clasificación