Java中InputStream转化为MultipartFile类型

由于工作需要,涉及到文件类型的转化,实际上MultipartFile有方法可以直接转化为InputStream,但是并没有办法可以从InputStream直接转化为MultipartFile。

网上的资料大概看了下,有两种简单的方案CommonsMultipartFile和MockMultipartFile,不过对我来说都不适用,因为我不能添加依赖。

我决定先看下MultipartFile怎么转化成InputStream。

public class CommonsMultipartFile implements MultipartFile, Serializable {
    protected static final Log logger = LogFactory.getLog(CommonsMultipartFile.class);
    private final FileItem fileItem;
    private final long size;
    private boolean preserveFilename = false;

    public CommonsMultipartFile(FileItem fileItem) {
        this.fileItem = fileItem;
        this.size = this.fileItem.getSize();
    }

很尴尬,进到getInputStream()方法中直接看到了CommonsMultipartFile实现类,看来我的起步依赖直接就包含了这个实现类,不用引入了,那接下来的事情就好办了,不过我还是决定继续往后看看

//CommonsMultipartFile中的方法
public InputStream getInputStream() throws IOException {
        if (!this.isAvailable()) {
            throw new IllegalStateException("File has been moved - cannot be read again");
        } else {
            InputStream inputStream = this.fileItem.getInputStream();
            return inputStream != null ? inputStream : StreamUtils.emptyInput();
        }
    }

可以看出,压力来到了fileItem这边,继续往后找,找到一个FileItem实现类

public class DiskFileItem implements FileItem {
    public static final String SERIALIZABLE_PROPERTY = DiskFileItem.class.getName() + ".serializable";
    private static final long serialVersionUID = 2237570099615271025L;
    public static final String DEFAULT_CHARSET = "ISO-8859-1";
    private static final String UID = UUID.randomUUID().toString().replace('-', '_');
    private static final AtomicInteger COUNTER = new AtomicInteger(0);
    private String fieldName;
    private final String contentType;
    private boolean isFormField;
    private final String fileName;
    private long size = -1L;
    private final int sizeThreshold;
    private final File repository;
    private byte[] cachedContent;
    private transient DeferredFileOutputStream dfos;
    private transient File tempFile;
    private File dfosFile;
    private FileItemHeaders headers;

    public DiskFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, File repository) {
        this.fieldName = fieldName;
        this.contentType = contentType;
        this.isFormField = isFormField;
        this.fileName = fileName;
        this.sizeThreshold = sizeThreshold;
        this.repository = repository;
    }

虽然这个FileItem类有构造方法,不过。。里面有一些属性确实没看明白是干啥的。然后继续往后

public InputStream getInputStream() throws IOException {
        if (!this.isInMemory()) {
            return new FileInputStream(this.dfos.getFile());
        } else {
            if (this.cachedContent == null) {
                this.cachedContent = this.dfos.getData();
            }

            return new ByteArrayInputStream(this.cachedContent);
        }
    }
public byte[] getData() {
        return this.memoryOutputStream != null ? this.memoryOutputStream.toByteArray() : null;
    }
public synchronized byte[] toByteArray() {
        int remaining = this.count;
        if (remaining == 0) {
            return EMPTY_BYTE_ARRAY;
        } else {
            byte[] newbuf = new byte[remaining];
            int pos = 0;
            Iterator var4 = this.buffers.iterator();

            while(var4.hasNext()) {
                byte[] buf = (byte[])var4.next();
                int c = Math.min(buf.length, remaining);
                System.arraycopy(buf, 0, newbuf, pos, c);
                pos += c;
                remaining -= c;
                if (remaining == 0) {
                    break;
                }
            }

            return newbuf;
        }

最终看起来这个toByteArray()方法是个干活的,干的活大概是把文件转成byte[]数组,那实际上有两种解决方案了,一种就是直接用CommonsMultipartFile(这个地方我看了网上才知道有工厂类可以创建),一种是自己转化成byte[]数组,然后在转化成CommonsMultipartFile

public void testOSSServiceImport(){
    File file = new File("test.png");
    DiskFileItem fileItem = (DiskFileItem) new DiskFileItemFactory().createItem("file",
            MediaType.ALL_VALUE, true, file.getName());

    try (InputStream input = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()) {
        IOUtils.copy(input, os);
    } catch (Exception e) {
        throw new IllegalArgumentException("Invalid file: " + e, e);
    }

    MultipartFile multi = new CommonsMultipartFile(fileItem);

}

这个是参考网上的CommonsMultipartFile用法

 /**
     * 获取封装得MultipartFile
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return MultipartFile
     */
    public MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
        FileItem fileItem = createFileItem(inputStream, fileName);
        //CommonsMultipartFile是feign对multipartFile的封装,但是要FileItem类对象
        return new CommonsMultipartFile(fileItem);
    }


    /**
     * FileItem类对象创建
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return FileItem
     */
    public FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[10 * 1024 * 1024];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {
            log.error("Stream copy exception", e);
            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);

                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);
                }
            }
        }

        return item;
    }

 

这个是用byte[]数组的转化

  • 15
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值