StandardMultipartFile.transferTo falls back to manual copy
Issue: SPR-15257
This commit is contained in:
parent
0662dbf044
commit
b73153cd7c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -27,7 +27,7 @@ import org.springframework.core.io.InputStreamSource;
|
|||
*
|
||||
* <p>The file contents are either stored in memory or temporarily on disk.
|
||||
* In either case, the user is responsible for copying file contents to a
|
||||
* session-level or persistent store as and if desired. The temporary storages
|
||||
* session-level or persistent store as and if desired. The temporary storage
|
||||
* will be cleared at the end of request processing.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
@ -50,6 +50,8 @@ public interface MultipartFile extends InputStreamSource {
|
|||
* but it typically will not with any other than Opera.
|
||||
* @return the original filename, or the empty String if no file has been chosen
|
||||
* in the multipart form, or {@code null} if not defined or not available
|
||||
* @see org.apache.commons.fileupload.FileItem#getName()
|
||||
* @see org.springframework.web.multipart.commons.CommonsMultipartFile#setPreserveFilename
|
||||
*/
|
||||
String getOriginalFilename();
|
||||
|
||||
|
@ -81,7 +83,7 @@ public interface MultipartFile extends InputStreamSource {
|
|||
|
||||
/**
|
||||
* Return an InputStream to read the contents of the file from.
|
||||
* The user is responsible for closing the stream.
|
||||
* <p>The user is responsible for closing the returned stream.
|
||||
* @return the contents of the file as stream, or an empty stream if empty
|
||||
* @throws IOException in case of access errors (if the temporary store fails)
|
||||
*/
|
||||
|
@ -91,18 +93,22 @@ public interface MultipartFile extends InputStreamSource {
|
|||
/**
|
||||
* Transfer the received file to the given destination file.
|
||||
* <p>This may either move the file in the filesystem, copy the file in the
|
||||
* filesystem, or save memory-held contents to the destination file.
|
||||
* If the destination file already exists, it will be deleted first.
|
||||
* <p>If the file has been moved in the filesystem, this operation cannot
|
||||
* be invoked again. Therefore, call this method just once to be able to
|
||||
* work with any storage mechanism.
|
||||
* <p><strong>Note:</strong> when using Servlet 3.0 multipart support you
|
||||
* need to configure the location relative to which files will be copied
|
||||
* as explained in {@link javax.servlet.http.Part#write}.
|
||||
* @param dest the destination file
|
||||
* filesystem, or save memory-held contents to the destination file. If the
|
||||
* destination file already exists, it will be deleted first.
|
||||
* <p>If the target file has been moved in the filesystem, this operation
|
||||
* cannot be invoked again afterwards. Therefore, call this method just once
|
||||
* in order to work with any storage mechanism.
|
||||
* <p><b>NOTE:</b> Depending on the underlying provider, temporary storage
|
||||
* may be container-dependent, including the base directory for relative
|
||||
* destinations specified here (e.g. with Servlet 3.0 multipart handling).
|
||||
* For absolute destinations, the target file may get renamed/moved from its
|
||||
* temporary location or newly copied, even if a temporary copy already exists.
|
||||
* @param dest the destination file (typically absolute)
|
||||
* @throws IOException in case of reading or writing errors
|
||||
* @throws IllegalStateException if the file has already been moved
|
||||
* in the filesystem and is not available anymore for another transfer
|
||||
* @see org.apache.commons.fileupload.FileItem#write(File)
|
||||
* @see javax.servlet.http.Part#write(String)
|
||||
*/
|
||||
void transferTo(File dest) throws IOException, IllegalStateException;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -165,7 +165,7 @@ public class CommonsMultipartFile implements MultipartFile, Serializable {
|
|||
if (logger.isDebugEnabled()) {
|
||||
String action = "transferred";
|
||||
if (!this.fileItem.isInMemory()) {
|
||||
action = isAvailable() ? "copied" : "moved";
|
||||
action = (isAvailable() ? "copied" : "moved");
|
||||
}
|
||||
logger.debug("Multipart file '" + getName() + "' with original filename [" +
|
||||
getOriginalFilename() + "], stored " + getStorageDescription() + ": " +
|
||||
|
@ -173,14 +173,18 @@ public class CommonsMultipartFile implements MultipartFile, Serializable {
|
|||
}
|
||||
}
|
||||
catch (FileUploadException ex) {
|
||||
throw new IllegalStateException(ex.getMessage());
|
||||
throw new IllegalStateException(ex.getMessage(), ex);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// Pass through when coming from FileItem directly
|
||||
throw ex;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// From I/O operations within FileItem.write
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.error("Could not transfer to file", ex);
|
||||
throw new IOException("Could not transfer to file: " + ex.getMessage());
|
||||
throw new IOException("File transfer failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.multipart.support;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
|
@ -307,6 +308,15 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
|
|||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
this.part.write(dest.getPath());
|
||||
if (dest.isAbsolute() && !dest.exists()) {
|
||||
// Servlet 3.0 Part.write is not guaranteed to support absolute file paths:
|
||||
// may translate the given path to a relative location within a temp dir
|
||||
// (e.g. on Jetty whereas Tomcat and Undertow detect absolute paths).
|
||||
// At least we offloaded the file from memory storage; it'll get deleted
|
||||
// from the temp dir eventually in any case. And for our user's purposes,
|
||||
// we can manually copy it to the requested location as a fallback.
|
||||
FileCopyUtils.copy(this.part.getInputStream(), new FileOutputStream(dest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue