关于OSS的购买和配置,看这篇文章
https://blog.csdn.net/lianzhang861/article/details/82776197
我用的Spring mvc,maven项目,
1.首先引入包
<dependency> <groupId>com.aliyun.ossgroupId> <artifactId>aliyun-sdk-ossartifactId> <version>2.8.3version> dependency>
2.创建OSSUtil
@Controllerpublic 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 streamConcurrentLinkedQueue = new ConcurrentLinkedQueue<>( Arrays.asList(inputStreams)); Iterator 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")@ResponseBodypublic void uploadFileToOss( @RequestParam Mapparams, @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,代码中有写到