gpt4 book ai didi

Java : InputStream to Multi-part file conversion, 结果文件为空

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:40:52 26 4
gpt4 key购买 nike

我正在开发一个 Java 应用程序,我试图在其中从下载的 InputStream 创建一个多部分文件。不幸的是,它不工作,Multipart 文件是空的。在将其复制到 Multipart 之前,我检查了磁盘上 savedFile 的大小,它具有正确的大小、属性和内容。

我在转换中做错了什么,没有堆栈跟踪,因为我正在捕捉它。

代码:

// InputStream contains file data.
byte[] bytes = IOUtils.toByteArray(inputStream);

File file = new File(msg + "temp");
if (file.exists() && file.isDirectory()) {
OutputStream outputStream = new FileOutputStream(new File(msg + "temp" + "/" +
groupAttachments.getFileName()));
outputStream.write(bytes);
outputStream.close();
}
java.io.File savedFile = new java.io.File(msg + "temp" + "/" +
groupAttachments.getFileName());
DiskFileItem fileItem = new DiskFileItem("file", "text/plain", false,
savedFile.getName(), (int) savedFile.length(), savedFile.getParentFile());
fileItem.getOutputStream();
MultipartFile multipartFile = new CommonsMultipartFile(fileItem);

System.out.println("Saved file size is "+savedFile.length());
if (multipartFile.isEmpty()) {
System.out.println("Dropbox uploaded multipart file is empty");
} else {
System.out.println("Multipart file is not empty.");
}
this.dropboxTask.insertFile(multipartFile, "",
savedPersonalNoteObject.getNoteid(), (long) 0, true);
Path path = Paths.get(msg + "temp" + "/" + groupAttachments.getFileName());

控制台输出:

Multipart file is not empty
Bytes are not null
File path is /My Group
Input stream is not null
Saved file size is 4765
Dropbox uploaded multipart file is empty
Multipart file is empty
Bytes are not null

我在转换过程中做错了什么?你能帮忙的话,我会很高兴。多谢。

最佳答案

DiskFileItem 使用 DeferredFileOutputStream,它使用内存中的字节数组,只有在实际传输字节时才会填充。由于直接使用文件,实际上没有复制任何字节,字节数组永远不会被填充。自己看源码:
源代码CommonsMultipartFile
源代码DiskFileItem
源代码DeferredFileOutputStream

因此,不是仅仅调用 fileItem.getOutputStream();,而是传输字节以填充内存中的字节数组:

try (OutputStream out = fileItem.getOutputStream();
InputStream in = Files.newInputStream(file.toPath())) {
IOUtils.copy(in, dfos);
}

然后 tranferTo 调用将起作用。
对于移动文件来说,这似乎有点麻烦:CommonsMultipartFile 只调用 transferTo< 中的 fileItem.write((File)dest)/ 方法。下面是两个测试用例,一个使用 DiskFileItem,一个使用 LocalFileItemLocalFileItem 的代码如下所示。
我使用了依赖项 org.springframework:spring-web:4.2.2.RELEASEcommons-fileupload:commons-fileupload:1.3.1 junit:junit:4.12
测试类CommonMp:

import static org.junit.Assert.*;
import java.io.*;
import java.nio.charset.*;
import java.nio.file.*;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class CommonMp {

private final Charset CS = StandardCharsets.UTF_8;

@Test
public void testLocalMp() {

Path testInputFile = null, testOutputFile = null;
try {
testInputFile = prepareInputFile();
LocalFileItem lfi = new LocalFileItem(testInputFile);
CommonsMultipartFile cmf = new CommonsMultipartFile(lfi);
System.out.println("Empty: " + cmf.isEmpty());
testOutputFile = testInputFile.getParent().resolve("testMpOutput.txt");
cmf.transferTo(testOutputFile.toFile());
System.out.println("Size: " + cmf.getSize());
printOutput(testOutputFile);
} catch (Exception e) {
e.printStackTrace();
fail();
} finally {
deleteSilent(testInputFile, testOutputFile);
}
}

@Test
public void testMp() {

Path testInputFile = null, testOutputFile = null;
try {
testInputFile = prepareInputFile();
DiskFileItem di = new DiskFileItem("file", "text/plain", false, testInputFile.getFileName().toString(),
(int) Files.size(testInputFile), testInputFile.getParent().toFile());
try (OutputStream out = di.getOutputStream();
InputStream in = Files.newInputStream(testInputFile)) {
IOUtils.copy(in, out);
}
CommonsMultipartFile cmf = new CommonsMultipartFile(di);
System.out.println("Size: " + cmf.getSize());
testOutputFile = testInputFile.getParent().resolve("testMpOutput.txt");
cmf.transferTo(testOutputFile.toFile());
printOutput(testOutputFile);
} catch (Exception e) {
e.printStackTrace();
fail();
} finally {
deleteSilent(testInputFile, testOutputFile);
}
}

private Path prepareInputFile() throws IOException {

Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir"));
Path testInputFile = tmpDir.resolve("testMpinput.txt");
try (OutputStream out = Files.newOutputStream(testInputFile)){
out.write("Just a test.".getBytes(CS));
}
return testInputFile;
}

private void printOutput(Path p) throws IOException {

byte[] outBytes = Files.readAllBytes(p);
System.out.println("Output: " + new String(outBytes, CS));
}

private void deleteSilent(Path... paths) {

for (Path p : paths) {
try { if (p != null) p.toFile().delete(); } catch (Exception ignored) {}
}
}

}

自定义 LocalFileItem 类,YMMV!

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemHeaders;

public class LocalFileItem implements FileItem {

private static final long serialVersionUID = 2467880290855097332L;

private final Path localFile;

public LocalFileItem(Path localFile) {
this.localFile = localFile;
}

@Override
public void write(File file) throws Exception {
Files.move(localFile, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}

@Override
public long getSize() {

// Spring's CommonsMultipartFile caches the file size and uses it to determine availability.
long size = -1L;
try {
size = Files.size(localFile);
} catch (IOException ignored) {}
return size;
}

@Override
public void delete() {
localFile.toFile().delete();
}

/* *** properties and unsupported methods *** */

private FileItemHeaders headers;
private String contentType;
private String fieldName;
private boolean formField;

@Override
public FileItemHeaders getHeaders() {
return headers;
}

@Override
public void setHeaders(FileItemHeaders headers) {
this.headers = headers;
}

@Override
public InputStream getInputStream() throws IOException {
throw new IOException("Only method write(File) is supported.");
}

public void setContentType(String contentType) {
this.contentType = contentType;
}

@Override
public String getContentType() {
return contentType;
}

@Override
public String getName() {
return localFile.getFileName().toString();
}

@Override
public boolean isInMemory() {
return false;
}

@Override
public byte[] get() {
throw new RuntimeException("Only method write(File) is supported.");
}

@Override
public String getString(String encoding)
throws UnsupportedEncodingException {
throw new RuntimeException("Only method write(File) is supported.");
}

@Override
public String getString() {
throw new RuntimeException("Only method write(File) is supported.");
}

@Override
public String getFieldName() {
return fieldName;
}

@Override
public void setFieldName(String name) {
this.fieldName = name;
}

@Override
public boolean isFormField() {
return formField;
}

@Override
public void setFormField(boolean state) {
this.formField = state;
}

@Override
public OutputStream getOutputStream() throws IOException {
throw new IOException("Only method write(File) is supported.");
}

}

关于Java : InputStream to Multi-part file conversion, 结果文件为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33625906/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com