从多个休息请求中写入文件

时间:2013-12-31 10:17:21

标签: rest jersey-2.0

我写了一个休息服务来接收文件并保存。

问题在于,当我收到超过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。

更新:我想在这里实现的非常简单

  1. 我收到附带文件的请求数
  2. 我需要保存它们。如果mediaName和mediaType相同,那么我需要在文件名中添加一些内容并将其保存在同一位置
  3. 如果他们不同我没有问题
  4. 我面对当前代码的问题是,当我多次发布到同一个URL时,我根据自己的意愿创建了文件名,但文件内容不对,它们根据时间的不同而不同请求进来,只有最后一个POST的请求写得正确。

    EG。我有一个大小为250MB的zip文件,当我发布5次时,前四个将具有随机大小,第五个将具有完整的250MB,但前四个也应具有相同的内容。

1 个答案:

答案 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();
}