这里仅列举一些关键的代码,供大家学习参考。

前端:

// 暴露用户头像删除与更新功能相关的api接口
export const UserPicDeleteAndUpdateService = (storePic, picUrl) => {
    let params = new URLSearchParams()
    let fileName = storePic.slice(36) // 截取文件名部分
    params.append('fileName', fileName)
    params.append('picUrl', picUrl)
    return request.put('/delAndUpdate', params)
}
// 用户头像地址
const imgUrl= ref(userStore.userInfo.userPic ? userStore.userInfo.userPic : avatar)
// 数组:指定允许的图片类型
const allowedTypes = ['image/jpeg','image/png','image/webp','image/jpg']
// 文件上传前核验
const beforeAvatarUpload = (rawFile) => {
    if (!allowedTypes.includes(rawFile.type)) {
        ElMessage.error('文件非图片格式!')
        return false
    } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('图片大小不能超2MB!')
        return false
    }
    return true
}
// 图片上传成功的回调函数
const uploadSuccess = (result) => {
    // 回显图片内容
    imgUrl.value = result.data
}
// 点击更新用户头像时调用的处理方法
const updateAvatar = async () => {
    if (imgUrl.value === avatar) {
        ElMessage.error('请先选择图片文件')
        return
    }
    let result = await UserPicDeleteAndUpdateService(userStore.userInfo.userPic, imgUrl.value)// 删除上传的原用户头像并更新新头像
    ElMessage.success(result.message ? result.message : '修改成功')
    userStore.userInfo.userPic = imgUrl.value
}
<el-row>
            <el-col :span="12">
                <el-upload 
                    ref="uploadRef"
                    class="avatar-uploader" 
                    :show-file-list="false"
                    :auto-upload="true"
                    action="/api/upload"
                    name="file"
                    :headers="{'Authorization': tokenStore.token}"
                    :before-upload="beforeAvatarUpload"
                    :on-success="uploadSuccess"
                    >
                    <img v-if="imgUrl" :src="imgUrl" class="avatar" /> 
                </el-upload>
                <br />
                <el-button type="primary" :icon="Plus" size="large"  @click="uploadRef.$el.querySelector('input').click()">
                    选择图片
                </el-button>
                <el-button @click="updateAvatar" type="success" :icon="Upload" size="large">
                    更新头像
                </el-button>
            </el-col>
        </el-row>

后端:

导入的七牛云相关的两个依赖

		<dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>7.16.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
            <scope>compile</scope>
        </dependency>

工具类

@Component
public class QiniuUtil {
    // 构造一个带指定 Region 对象的配置类
    private static final Configuration cfg = new Configuration(Region.autoRegion());
    private static final UploadManager uploadManager = new UploadManager(cfg);
    // 上传凭证
    private static String ACCESS_KEY;
    private static String SECRET_KEY;
    private static String BUCKET;
    private static String DOMAIN;
    // 默认不指定key的情况下,以文件内容的hash值作为文件名

	// 凭证等信息配置在了yml配置文件中,这里获取值时不能在静态常量上直接通过@Value获取
    @Value("${qiniu.accessKey}")
    public void setAccessKey(String accessKey) {
        ACCESS_KEY = accessKey;
    }

    @Value("${qiniu.secretKey}")
    public void setSecretKey(String secretKey) {
        SECRET_KEY = secretKey;
    }

    @Value("${qiniu.bucket}")
    public void setBucket(String bucket) {
        BUCKET = bucket;
    }

    @Value("${qiniu.domain}")
    public void setDomain(String domain) {
        DOMAIN = domain;
    }

    private static Auth auth;
    private static BucketManager bucketManager;

    public QiniuUtil(@Value("${qiniu.accessKey}") String ak, @Value("${qiniu.secretKey}") String sk) {
        auth = Auth.create(ak, sk);
        bucketManager = new BucketManager(auth, cfg);
    }

    public static String uploadFile(InputStream is, String fileName) {
        try {
            String upToken = auth.uploadToken(BUCKET);
            Response response = uploadManager.put(is, fileName, upToken, null, null);
            // response.bodyString():{"hash":"Fo7JxhrAagwtka2eVJeMJNjBBZNC","key":"f20a7ad4-64fa-4d30-b41d-84f17d67db4e.webp"}
            // 图片url格式:你的domain/putRet.key

            // 解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            return DOMAIN + "/" + putRet.key;
        } catch (QiniuException ex) {
            ex.printStackTrace();
            if (ex.response != null) {
                System.err.println("ex.response:" + ex.response);
                String body = ex.response.toString();
                System.err.println("bode:" + body);
            }
        }
        return "";
    }

    public static void delFile(String fileName) {
        try {
            bucketManager.delete(BUCKET, fileName);
        } catch (QiniuException ex) {
            // 如果遇到异常,说明删除失败,可以自行修改异常的处理逻辑
            System.err.println("ex.code()" + ex.code());
            System.err.println(ex.response.toString());
        }
    }

	// 获取上传的所有文件名集合
    public static List<String> getFiles() {
        // 文件名前缀
        String prefix = "";
        // 每次迭代的长度限制,最大1000,推荐值 1000
        int limit = 10;
        // 指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
        String delimiter = "";
        List<String> fileNames = new ArrayList<>();
        // 列举空间文件列表
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(BUCKET, prefix, limit, delimiter);
        while (fileListIterator.hasNext()) {
            // 处理获取的file list结果
            FileInfo[] items = fileListIterator.next();
            for (FileInfo item : items) {
                fileNames.add(item.key);
                /*item.key 文件名;item.hash ETag;item.fsize 文件大小;item.mimeType 文件类型*/
            }
        }
        return fileNames;
    }
}

响应实体类

// 统一响应结果
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Result<T> {
    private Integer code;// 业务状态码  1-成功  0-失败
    private String message;// 提示信息
    private T data;// 响应数据

    // 快速返回操作成功响应结果(带响应数据)
    public static <E> Result<E> success(E data) {
        return new Result<>(1, "操作成功", data);
    }
	// 返回操作成功响应结果(带自定义的提示信息)
    public static Result ok(String mes) {
        return new Result(1, mes, null);
    }
    // 快速返回操作成功响应结果
    public static Result success() {
        return new Result(1, "操作成功", null);
    }

    public static Result error(String message) {
        return new Result(0, message, null);
    }
}

控制器类

@RestController
public class FileController {
    @Autowired
    private UserService userService;

    @PostMapping("/upload")
    public Result<String> upload(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String avatarUrl = QiniuUtil.uploadFile(file.getInputStream(), fileName);
        return Result.success(avatarUrl);
    }

    @PutMapping("/delAndUpdate")
    public Result deleteAndUpdate(@RequestParam String fileName, @RequestParam String picUrl) {
        String mes = "";
        // 获取云存储空间中的文件名列表
        List<String> files = QiniuUtil.getFiles();
        if (files.isEmpty() || "".equals(fileName)) {
            mes = "云存储空间是空的或存储的用户头像状态为空,不执行原头像删除;新用户头像已同步";
        } else if (files.contains(fileName)){
            QiniuUtil.delFile(fileName);
        }
        userService.updateAvatar(picUrl);
        return Result.ok(mes);
    }
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐