阿里云存储对象OSS使用讲解二:java上传文件

关于OSS的购买和配置,看这篇文章

https://blog.csdn.net/lianzhang861/article/details/82776197

我用的Spring mvc,maven项目,

1.首先引入包

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

2.创建OSSUtil

@Controller
public class OSSUtil {

    @Value("${endpoint}")
    private String endpoint;
    @Value("${accessKeyId}")
    private String accessKeyId;
    @Value("${accessKeySecret}")
    private String accessKeySecret;
    @Value("${bucketName}")
    private String bucketName;

    //oss域名前缀,我绑定了CNAME所以用我的域名
    private String key = "http://oss.zhulianzhang.com/";

    /**
     * 上传文件
     *
     * @param fileName 文件名
     * @param inputStream 流
     */
    public String uploadFileToOss(String fileName, InputStream inputStream,String folder) {
        /**
         * 创建OSS客户端
         */
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        try {
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String[] names = fileName.split("[.]");
            String name = uuid + "." + names[names.length - 1];
            ossClient.putObject(new PutObjectRequest(bucketName, folder + name, inputStream));
            return key + folder + name;
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }
        return null;
    }


    /**
     * 多文件上传
     */
    public String[] uploadFilesToOss(String[] fileNames, InputStream[] inputStreams,String folder) {
        /**
         * 创建OSS客户端
         */
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        try {
            ConcurrentLinkedQueue concurrentLinkedQueue = new ConcurrentLinkedQueue(
                    Arrays.asList(fileNames));
            ConcurrentLinkedQueue<InputStream> streamConcurrentLinkedQueue = new ConcurrentLinkedQueue<>(
                    Arrays.asList(inputStreams));
            Iterator<InputStream> inputStreamss = streamConcurrentLinkedQueue.iterator();
            ConcurrentLinkedQueue c = new ConcurrentLinkedQueue();
            for (Iterator<String> iterator = concurrentLinkedQueue.iterator();
                 iterator.hasNext() && inputStreamss.hasNext(); ) {
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                String[] names = iterator.next().split("[.]");
                String name = uuid + "." + names[names.length - 1];
                ossClient.putObject(new PutObjectRequest(bucketName, folder + name, inputStreamss.next()));
                c.add(key + folder + name);
            }
            return (String[]) c.toArray(new String[0]);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }
        return null;
    }


    /**
     * 删除图片 警告:在没有调用其他方法的情况下,请调用closeClient方法
     *
     * @param url URL全路径
     */
    public void deleteImg(String url,String folder) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        if (url == null || "".equals(url)) {
            return;
        }
        String[] paths = url.split("[.]");
        /**
         * 文件夹是否存在
         */
        if (!ossClient.doesObjectExist(bucketName, folder)) {
            ossClient.putObject(bucketName, folder, new ByteArrayInputStream(new byte[0]));
        }
        String[] name = paths[paths.length - 2].split("[/]");
        /**
         * 对象是否存在
         */
        if (ossClient
                .doesObjectExist(bucketName,
                        folder + name[name.length - 1] + "." + paths[paths.length - 1])) {
            /**
             * 删除存在对象
             */
            ossClient
                    .deleteObject(bucketName, folder + name[name.length - 1] + "." + paths[paths.length - 1]);
        }
        ossClient.shutdown();
    }

}

配置信息我卸载config.properties调用的,调用方法可以看这篇文章有提到

https://blog.csdn.net/lianzhang861/article/details/82255867

注意:

@Value("${endpoint}")
private String endpoint;

这样调用配置的方法貌似只能在controller中使用,所以我在util类前面也加了@controller

config.properties中的配置:

 

3.controller中使用

@Value("${imgFolder}")
private String imgFolder;
@Value("${videoFolder}")
private String videoFolder;
@Value("${coverFolder}")
private String coverFolder;


// 上传文件到阿里云OSS
@RequestMapping(value = "uploadFileToOss", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
@ResponseBody
public void uploadFileToOss(
        @RequestParam Map<String,Object> params,
        @RequestParam(value = "file") MultipartFile[] files,
        HttpServletRequest request
){
    String folder="";
    //判断文件类型分配不同文件夹下
    if(params.get("attachmentType").equals("IMAGE")){
        folder=imgFolder;
    }else if(params.get("attachmentType").equals("VIDEO")){
        folder=videoFolder;
    }

    int userId=((TSystemUser)request.getSession().getAttribute("USER")).getUserId();
    params.put("userId",userId);
    //缩略图,不是视频则保存空
    params.put("attachmentThumbnail","");
    try {
        //因为springmvc注解访问了inputstream封装成了MultipartFile,而inputstream只能被碰一次,所以得把MultipartFile
        //在转换成inputstream格式,因为oss上传只接受inputstream格式
        for (MultipartFile file : files) {    //将MultipartFile转换成inputStream
            String fileName = file.getOriginalFilename();
            CommonsMultipartFile cFile = (CommonsMultipartFile) file;
            DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
            InputStream inputStream = fileItem.getInputStream();
            InputStream stream1;
            InputStream stream2;
            if(params.get("attachmentType").equals("VIDEO")){
                //因为inputStream只能读取一次,所以要复制出来一份
                ByteArrayOutputStream baosOutputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) > -1) {
                    baosOutputStream.write(buffer, 0, len);
                }
                baosOutputStream.flush();

                stream1 = new ByteArrayInputStream(baosOutputStream.toByteArray());
                stream2 = new ByteArrayInputStream(baosOutputStream.toByteArray());
                baosOutputStream.close();

            }else{
                stream1=inputStream;
                stream2=inputStream;
            }
            //上传文件到oss返回路径
            String fileUrl= ossUtil.uploadFileToOss(fileName,stream1,folder);
            params.put("attachmentUrl",fileUrl);
            params.put("attachmentName",fileName);
            //如果是视频类型,则保存封面
            if(params.get("attachmentType").equals("VIDEO")){
                //用javacv进行视频截取帧
                FFmpegFrameGrabber ff = new FFmpegFrameGrabber(stream2);
                ff.start();
                int length = ff.getLengthInFrames();
                int i = 0;
                Frame f = null;
                while (i < length) {
                    // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                    f = ff.grabImage();
                    if ((i > 5) && (f.image != null)) {
                        break;
                    }
                    i++;
                }
                //为了将图片上传OSS,将其转换成inputStream格式
                InputStream cover=FrameToBufferedImage(f);
                //上传视频封面到oss返回路径
                String coverUrl= ossUtil.uploadFileToOss("cover.jpg",cover,coverFolder);
                params.put("attachmentThumbnail",coverUrl);
            }
            inputStream.close();
            stream1.close();
            stream2.close();
            attachmentService.saveFile(params);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

//把Frame转换成inputStream类型
public static InputStream FrameToBufferedImage(Frame frame) throws IOException {
    //创建BufferedImage对象
    Java2DFrameConverter converter = new Java2DFrameConverter();
    BufferedImage bufferedImage = converter.getBufferedImage(frame);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIO.write(bufferedImage, "jpg", os);
    InputStream is = new ByteArrayInputStream(os.toByteArray());

    return is;
}

我写的是文件上传的通用接口,其中包括视频上传后截取视频封面,所以比较复杂,

关于视频截取封面,参考这个https://blog.csdn.net/lianzhang861/article/details/82014460

坑:

1.oss上传需要传入文件流inputStream或者file类型,而spring mvc接收前台form表单传输的文件流会访问inputstream,转为MultipartFile格式,inputstream只能访问一次,所以在spring mvc中直接获取inputstream会报空,所以需要将multipart格式转化成inputstream

2.转化后的inputstream也只能用一次,而我上传视频时需要先上传文件,在上传截取的封面,需要使用两次inputstream,所以必须复制出来一份inputstream,代码中有写到

 

 

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆趣编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值