Index: source/ch/ethz/ssh2/sftp/SFTPv3Client.java
===================================================================
--- source/ch/ethz/ssh2/sftp/SFTPv3Client.java	(revision 7535)
+++ source/ch/ethz/ssh2/sftp/SFTPv3Client.java	(working copy)
@@ -1291,6 +1291,46 @@
     }
 
     /**
+     * A read  is divided into multiple requests sent sequentially before
+     * reading any status from the server
+     */
+    private static class OutstandingAck {
+        int req_id;
+        /**
+         * Read offset to request on server starting at the file offset for the first request.
+         */
+        long serverOffset;
+        /**
+         * Length of requested data
+         */
+        int len;
+        /**
+         * Offset in destination buffer
+         */
+        int dstOffset;
+        /**
+         * Temporary buffer
+         */
+        byte[] buffer;
+    }
+
+    private void sendWriteRequest(int id, SFTPv3FileHandle handle, long offset, int len, byte[] src, int srcoff) throws IOException {
+        TypesWriter tw = new TypesWriter();
+        tw.writeString(handle.fileHandle, 0, handle.fileHandle.length);
+        tw.writeUINT64(offset);
+        tw.writeString(src, srcoff, len);
+
+        log.log("Sending SSH_FXP_WRITE (" + id + ") " + offset + "/" + len);
+        sendMessage(Packet.SSH_FXP_WRITE, id, tw.getBytes());
+    }
+
+    /**
+     * Mapping request ID to request.
+     */
+    Map<Integer, OutstandingAck> pendingWQueue
+            = new HashMap<Integer, OutstandingAck>();
+
+    /**
      * Write bytes to a file. If <code>len</code> &gt; 32768, then the write operation will
      * be split into multiple writes.
      *
@@ -1303,29 +1343,62 @@
      */
     public void upload(SFTPv3FileHandle handle, long fileOffset, byte[] src, int srcoff, int len) throws IOException {
         checkHandleValidAndOpen(handle);
+        /* check that we didn't received anything bad in our queue, empty the input buffer */
+        if( (0 >= len) && pendingWQueue.size() > 0 )
+        {
+            while(!pendingWQueue.isEmpty()) {
+                byte[] resp = receiveMessage(34000);
 
+                TypesReader tr = new TypesReader(resp);
+
+                int t = tr.readByte();
+
+                int rep_id = tr.readUINT32();
+                OutstandingAck rack = pendingWQueue.get(rep_id);
+
+                if(null == rack) {
+                    throw new IOException("The server sent an invalid id field.");
+                }
+                pendingWQueue.remove(rep_id);
+
+                if(t != Packet.SSH_FXP_STATUS) {
+                throw new IOException("The SFTP server sent an unexpected packet type (" + t + ")");
+                }
+
+                int errorCode = tr.readUINT32();
+
+                if(errorCode == ErrorCodes.SSH_FX_OK) {
+                    continue;
+                }
+
+                String errorMessage = tr.readString();
+
+                throw new SFTPException(errorMessage, errorCode);
+
+            }
+	}
         while(len > 0) {
             int writeRequestLen = len;
 
             if(writeRequestLen > 32768) {
                 writeRequestLen = 32768;
             }
+	    OutstandingAck ack = new OutstandingAck();
+            ack.req_id = generateNextRequestID();
+            ack.serverOffset = fileOffset;
+            ack.len = writeRequestLen;
 
-            int req_id = generateNextRequestID();
+            sendWriteRequest(ack.req_id, handle, ack.serverOffset, ack.len, src, srcoff);
 
-            TypesWriter tw = new TypesWriter();
-            tw.writeString(handle.fileHandle, 0, handle.fileHandle.length);
-            tw.writeUINT64(fileOffset);
-            tw.writeString(src, srcoff, writeRequestLen);
+	    pendingWQueue.put(ack.req_id, ack);
 
-            log.log("Sending SSH_FXP_WRITE...");
-            sendMessage(Packet.SSH_FXP_WRITE, req_id, tw.getBytes());
+            fileOffset += ack.len;
 
-            fileOffset += writeRequestLen;
+            srcoff += ack.len;
+            len -= ack.len;
 
-            srcoff += writeRequestLen;
-            len -= writeRequestLen;
-
+            if(pendingWQueue.size() >= parallelism)
+            {
             byte[] resp = receiveMessage(34000);
 
             TypesReader tr = new TypesReader(resp);
@@ -1333,9 +1406,12 @@
             int t = tr.readByte();
 
             int rep_id = tr.readUINT32();
-            if(rep_id != req_id) {
+            OutstandingAck rack = pendingWQueue.get(rep_id);
+
+            if(null == rack) {
                 throw new IOException("The server sent an invalid id field.");
             }
+            pendingWQueue.remove(rep_id);
 
             if(t != Packet.SSH_FXP_STATUS) {
                 throw new IOException("The SFTP server sent an unexpected packet type (" + t + ")");
@@ -1350,6 +1426,7 @@
             String errorMessage = tr.readString();
 
             throw new SFTPException(errorMessage, errorCode);
+            }
         }
     }
 
Index: source/ch/cyberduck/core/sftp/SFTPPath.java
===================================================================
--- source/ch/cyberduck/core/sftp/SFTPPath.java	(revision 7535)
+++ source/ch/cyberduck/core/sftp/SFTPPath.java	(working copy)
@@ -528,6 +528,10 @@
                             this.getParent().getAbsolute(),
                             "0" + this.attributes().getPermission().getOctalString());
                 }
+                // No parallel requests if the file size is smaller than the buffer.
+                this.getSession().sftp().setDownloadRequestParallelism(
+                        (int) (this.attributes().getSize() / Preferences.instance().getInteger("connection.chunksize")) + 1
+                );
                 this.upload(out, in, throttle, listener);
             }
         }
