我写了一个休息服务来接收文件并保存。
问题在于,当我收到超过2个请求时,不会写入文件,只会考虑并写入最后一个请求。
这是我的代码:
@POST
@RequestMapping(value = "/media/{mediaName}/{mediaType}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@ResponseBody
public String updateResourceLocally(@FormDataParam("rawData") InputStream rawData, @PathVariable("mediaName") String mediaName, @PathVariable("mediaType") String mediaType) {
logger.info("Entering updateResourceLocally for " + jobId + "; for media type: " + mediaType);
final String storeDir = "/tmp/test/" + mediaName + ("/");
final String finalExtension = mediaType;
final InputStream finalRawData = rawData;
// new Thread(new Runnable() {
// public void run() {
// writeToFile(finalRawData, storeDir, finalExtension);
// }
// }).start();
writeToFile(finalRawData, storeDir, finalExtension);
// int poolSize = 100;
// ExecutorService executor = Executors.newFixedThreadPool(poolSize);
// executor.execute(new Runnable() {
// @Override
// public void run() {
// writeToFile(rawData, storeDir, finalExtension);
// }
// });
logger.info("File uploaded to : " + storeDir);
return "Success 200";
}
我试图将writeToFile放入线程中,但仍然没有成功。这就是writeToFile所做的事情
public synchronized void writeToFile(InputStream rawData,
String uploadedFileLocation, String extension) {
StringBuilder finalFileName = null;
String currentIncrement = "";
String fileName = "raw";
try {
File file = new File(uploadedFileLocation);
if (!file.exists()) {
file.mkdirs();
}
while (true) {
finalFileName = new StringBuilder(fileName);
if (!currentIncrement.equals("")) {
finalFileName.append("_").append(currentIncrement).append(extension);
}
File f = new File(uploadedFileLocation + finalFileName);
if (f.exists()) {
if (currentIncrement.equals("")) {
currentIncrement = "1";
} else {
currentIncrement = (Integer.parseInt(currentIncrement) + 1) + "";
}
} else {
break;
}
}
int read = 0;
byte[] bytes = new byte[1024];
OutputStream out = new FileOutputStream(new File(uploadedFileLocation + finalFileName));
while ((read = rawData.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
writeToFile创建一个文件夹并写入一个文件,如果该文件已经存在,它会附加1然后相应地增加1并写入文件,所以我会得到raw.zip,raw-1.zip等。 / p>
我认为输入流字节丢失了,我的假设是否正确?
注意:我没有UI客户端,我正在使用Poster扩展Firefox。
更新:我想在这里实现的非常简单
我面对当前代码的问题是,当我多次发布到同一个URL时,我根据自己的意愿创建了文件名,但文件内容不对,它们根据时间的不同而不同请求进来,只有最后一个POST的请求写得正确。
EG。我有一个大小为250MB的zip文件,当我发布5次时,前四个将具有随机大小,第五个将具有完整的250MB,但前四个也应具有相同的内容。
答案 0 :(得分:1)
您必须将流副本与自由文件名分配分开。流复制必须在调用线程(泽西服务)内完成。只有文件命名操作必须对所有线程/请求都是通用的。
以下是您的代码,其中包含一些重构:
<强> getNextFilename 强>
必须同步此文件命名操作,以确保每个调用都提供一个免费名称。此函数创建一个空文件以保证下一次调用工作,因为该函数依赖于file.exists()。
public synchronized File getNextFilename(String uploadedFileLocation, String extension)
throws IOException
{
// This function MUST be synchronized to guarantee unicity of files names
// Synchronized functions must be the shortest possible to avoid threads waiting each other.
// No long job such as copying streams here !
String fileName = "raw";
//Create directories (if not already existing)
File dir = new File(uploadedFileLocation);
if (!dir.exists())
dir.mkdirs();
//Search for next free filename (raw.<extension>, else raw_<increment>.<extension>)
int currentIncrement = 0;
String finalFileName = fileName + "." + extension;
File f = new File(uploadedFileLocation + finalFileName);
while (f.exists())
{
currentIncrement++;
finalFileName = fileName + "_" + currentIncrement + "." + extension;
f = new File(uploadedFileLocation + finalFileName);
}
//Creates the file with size 0 in order to physically reserve the file "raw_<n>.extension",
//so the next call to getNextFilename will find it (f.exists) and will return "raw_<n+1>.extension"
f.createNewFile();
//The file exists, let the caller fill it...
return f;
}
<强>将writeToFile 强>
不得同步!
public void writeToFile(InputStream rawData, String uploadedFileLocation, String extension)
throws IOException
{
//(1) Gets next available filename (creates the file with 0 size)
File file = getNextFilename(uploadedFileLocation, extension);
//(2) Copies data from inputStream to file
int read = 0;
byte[] bytes = new byte[1024];
OutputStream out = new FileOutputStream(file);
while ((read = rawData.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
}