Toggle navigation
Toggle navigation
This project
Loading...
Sign in
iOS
/
asi-http-request
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Ben Copsey
2009-03-16 18:32:41 +0000
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
4f5ae4694625def1cfa68183fa1fc7eb9070967b
4f5ae469
1 parent
49f9d131
Added the ability to resume large file downloads
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
133 additions
and
10 deletions
ASIFormDataRequestTests.m
ASIHTTPRequest.h
ASIHTTPRequest.m
ASIHTTPRequestTests.m
ASINetworkQueue.m
ASINetworkQueueTests.h
ASINetworkQueueTests.m
ASIFormDataRequestTests.m
View file @
4f5ae46
...
...
@@ -50,7 +50,7 @@
success
=
([[
request
responseString
]
isEqualToString
:[
NSString
stringWithFormat
:
@"post_var: %@
\r\n
post_var2: %@
\r\n
post_var3: %@
\r\n
file_name: %@
\r\n
file_size: %hu"
,
@"foo"
,
d
,
v
,
@"file"
,
size
]]);
GHAssertTrue
(
success
,
@"Failed to upload the correct data (using NSData)"
);
}
@end
...
...
ASIHTTPRequest.h
View file @
4f5ae46
...
...
@@ -179,6 +179,8 @@ typedef enum _ASINetworkErrorType {
NSStringEncoding
defaultResponseEncoding
;
NSStringEncoding
responseEncoding
;
BOOL
allowResumeForFileDownloads
;
}
#pragma mark init / dealloc
...
...
@@ -311,7 +313,7 @@ typedef enum _ASINetworkErrorType {
@property
(
assign
)
BOOL
useKeychainPersistance
;
@property
(
assign
)
BOOL
useSessionPersistance
;
@property
(
retain
)
NSString
*
downloadDestinationPath
;
@property
(
retain
,
readonly
)
NSString
*
temporaryFileDownloadPath
;
@property
(
retain
)
NSString
*
temporaryFileDownloadPath
;
@property
(
assign
)
SEL
didFinishSelector
;
@property
(
assign
)
SEL
didFailSelector
;
@property
(
retain
,
readonly
)
NSString
*
authenticationRealm
;
...
...
@@ -339,4 +341,5 @@ typedef enum _ASINetworkErrorType {
@property
(
assign
)
NSStringEncoding
defaultResponseEncoding
;
@property
(
assign
)
NSStringEncoding
responseEncoding
;
@property
(
assign
)
BOOL
allowCompressedResponse
;
@property
(
assign
)
BOOL
allowResumeForFileDownloads
;
@end
...
...
ASIHTTPRequest.m
View file @
4f5ae46
...
...
@@ -81,9 +81,11 @@ static NSError *ASIUnableToCreateRequestError;
[
self
setUploadBufferSize
:
0
];
[
self
setResponseHeaders
:
nil
];
[
self
setTimeOutSeconds
:
10
];
[
self
setAllowResumeForFileDownloads
:
NO
];
[
self
setUseKeychainPersistance
:
NO
];
[
self
setUseSessionPersistance
:
YES
];
[
self
setUseCookiePersistance
:
YES
];
[
self
setRawResponseData
:
nil
];
[
self
setRequestCookies
:[[[
NSMutableArray
alloc
]
init
]
autorelease
]];
[
self
setDidFinishSelector
:
@selector
(
requestFinished
:)];
[
self
setDidFailSelector
:
@selector
(
requestFailed
:)];
...
...
@@ -272,6 +274,12 @@ static NSError *ASIUnableToCreateRequestError;
[
self
addRequestHeader
:
@"Accept-Encoding"
value
:
@"gzip"
];
}
// Should this request resume an existing download?
if
([
self
allowResumeForFileDownloads
]
&&
[
self
downloadDestinationPath
]
&&
[
self
temporaryFileDownloadPath
]
&&
[[
NSFileManager
defaultManager
]
fileExistsAtPath
:[
self
temporaryFileDownloadPath
]])
{
unsigned
long
long
downloadedSoFar
=
[[[
NSFileManager
defaultManager
]
fileAttributesAtPath
:[
self
temporaryFileDownloadPath
]
traverseLink
:
NO
]
fileSize
];
[
self
addRequestHeader
:
@"Range"
value
:[
NSString
stringWithFormat
:
@"bytes=%llu-"
,
downloadedSoFar
]];
}
// Add custom headers
NSDictionary
*
headers
;
...
...
@@ -322,8 +330,9 @@ static NSError *ASIUnableToCreateRequestError;
contentLength
=
0
;
}
[
self
setResponseHeaders
:
nil
];
[
self
setRawResponseData
:[[[
NSMutableData
alloc
]
init
]
autorelease
]];
if
(
!
[
self
downloadDestinationPath
])
{
[
self
setRawResponseData
:[[[
NSMutableData
alloc
]
init
]
autorelease
]];
}
// Create the stream for the request.
readStream
=
CFReadStreamCreateForStreamedHTTPRequest
(
kCFAllocatorDefault
,
request
,
readStream
);
if
(
!
readStream
)
{
...
...
@@ -431,10 +440,14 @@ static NSError *ASIUnableToCreateRequestError;
if
(
rawResponseData
)
{
[
self
setRawResponseData
:
nil
];
// If we were downloading to a file
, let's remove it
// If we were downloading to a file
}
else
if
(
temporaryFileDownloadPath
)
{
[
outputStream
close
];
[[
NSFileManager
defaultManager
]
removeItemAtPath
:
temporaryFileDownloadPath
error
:
NULL
];
// If we haven't said we might want to resume, let's remove the temporary file too
if
(
!
[
self
allowResumeForFileDownloads
])
{
[[
NSFileManager
defaultManager
]
removeItemAtPath
:
temporaryFileDownloadPath
error
:
NULL
];
}
}
[
self
setResponseHeaders
:
nil
];
...
...
@@ -755,6 +768,7 @@ static NSError *ASIUnableToCreateRequestError;
BOOL
isAuthenticationChallenge
=
NO
;
CFHTTPMessageRef
headers
=
(
CFHTTPMessageRef
)
CFReadStreamCopyProperty
(
readStream
,
kCFStreamPropertyHTTPResponseHeader
);
if
(
CFHTTPMessageIsHeaderComplete
(
headers
))
{
CFDictionaryRef
headerFields
=
CFHTTPMessageCopyAllHeaderFields
(
headers
);
[
self
setResponseHeaders
:(
NSDictionary
*
)
headerFields
];
CFRelease
(
headerFields
);
...
...
@@ -1083,9 +1097,14 @@ static NSError *ASIUnableToCreateRequestError;
// Are we downloading to a file?
if
(
downloadDestinationPath
)
{
if
(
!
outputStream
)
{
[
temporaryFileDownloadPath
release
];
temporaryFileDownloadPath
=
[[
NSTemporaryDirectory
()
stringByAppendingPathComponent
:[[
NSProcessInfo
processInfo
]
globallyUniqueString
]]
retain
];
outputStream
=
[[
NSOutputStream
alloc
]
initToFileAtPath
:
temporaryFileDownloadPath
append
:
NO
];
BOOL
append
=
NO
;
if
(
!
[
self
temporaryFileDownloadPath
])
{
[
self
setTemporaryFileDownloadPath
:[
NSTemporaryDirectory
()
stringByAppendingPathComponent
:[[
NSProcessInfo
processInfo
]
globallyUniqueString
]]];
}
else
if
([
self
allowResumeForFileDownloads
])
{
append
=
YES
;
}
outputStream
=
[[
NSOutputStream
alloc
]
initToFileAtPath
:
temporaryFileDownloadPath
append
:
append
];
[
outputStream
open
];
}
[
outputStream
write
:
buffer
maxLength
:
bytesRead
];
...
...
@@ -1108,7 +1127,7 @@ static NSError *ASIUnableToCreateRequestError;
}
[
progressLock
lock
];
complete
=
YES
;
[
self
updateProgressIndicators
];
[
self
updateProgressIndicators
];
if
(
readStream
)
{
CFReadStreamClose
(
readStream
);
...
...
@@ -1442,4 +1461,5 @@ static NSError *ASIUnableToCreateRequestError;
@synthesize
defaultResponseEncoding
;
@synthesize
responseEncoding
;
@synthesize
allowCompressedResponse
;
@synthesize
allowResumeForFileDownloads
;
@end
...
...
ASIHTTPRequestTests.m
View file @
4f5ae46
...
...
@@ -504,5 +504,29 @@
}
-
(
void
)
testPartialFetch
{
NSString
*
downloadPath
=
[[[[
NSBundle
mainBundle
]
bundlePath
]
stringByDeletingLastPathComponent
]
stringByAppendingPathComponent
:
@"testfile.txt"
];
NSString
*
tempPath
=
[[[[
NSBundle
mainBundle
]
bundlePath
]
stringByDeletingLastPathComponent
]
stringByAppendingPathComponent
:
@"tempfile.txt"
];
NSString
*
partialContent
=
@"This file should be exactly 163 bytes long when encoded as UTF8, Unix line breaks with no BOM.
\n
"
;
[
partialContent
writeToFile
:
tempPath
atomically
:
NO
encoding
:
NSASCIIStringEncoding
error
:
nil
];
NSURL
*
url
=
[[[
NSURL
alloc
]
initWithString
:
@"http://allseeing-i.com/ASIHTTPRequest/Tests/test_partial_download.txt"
]
autorelease
];
ASIHTTPRequest
*
request
=
[[[
ASIHTTPRequest
alloc
]
initWithURL
:
url
]
autorelease
];
[
request
setDownloadDestinationPath
:
downloadPath
];
[
request
setTemporaryFileDownloadPath
:
tempPath
];
[
request
setAllowResumeForFileDownloads
:
YES
];
[
request
start
];
BOOL
success
=
([
request
contentLength
]
==
68
);
GHAssertTrue
(
success
,
@"Failed to download a segment of the data"
);
NSString
*
content
=
[
NSString
stringWithContentsOfFile
:
downloadPath
];
NSString
*
newPartialContent
=
[
content
substringFromIndex
:
95
];
success
=
([
newPartialContent
isEqualToString
:
@"This is the content we ought to be getting if we start from byte 95."
]);
GHAssertTrue
(
success
,
@"Failed to append the correct data to the end of the file?"
);
}
@end
...
...
ASINetworkQueue.m
View file @
4f5ae46
...
...
@@ -139,6 +139,13 @@
if
([[
request
requestMethod
]
isEqualToString
:
@"GET"
])
{
ASIHTTPRequest
*
HEADRequest
=
[[[
ASIHTTPRequest
alloc
]
initWithURL
:[
request
url
]]
autorelease
];
[
HEADRequest
setMainRequest
:
request
];
//If we're downloading to a file, and we already have a partial download to start from
if
([
request
allowResumeForFileDownloads
]
&&
[
request
downloadDestinationPath
]
&&
[
request
temporaryFileDownloadPath
]
&&
[[
NSFileManager
defaultManager
]
fileExistsAtPath
:[
request
temporaryFileDownloadPath
]])
{
unsigned
long
long
downloadedSoFar
=
[[[
NSFileManager
defaultManager
]
fileAttributesAtPath
:[
request
temporaryFileDownloadPath
]
traverseLink
:
NO
]
fileSize
];
[
HEADRequest
addRequestHeader
:
@"Range"
value
:[
NSString
stringWithFormat
:
@"bytes=%llu-"
,
downloadedSoFar
]];
}
[
self
addHEADOperation
:
HEADRequest
];
//Tell the request not to reset the progress indicator when it gets a content-length, as we will get the length from the HEAD request
...
...
ASINetworkQueueTests.h
View file @
4f5ae46
...
...
@@ -25,6 +25,7 @@
-
(
void
)
testProgress
;
-
(
void
)
testProgressWithAuthentication
;
-
(
void
)
testWithNoListener
;
-
(
void
)
testPartialResume
;
-
(
void
)
setProgress
:(
float
)
newProgress
;
...
...
ASINetworkQueueTests.m
View file @
4f5ae46
...
...
@@ -303,5 +303,73 @@ static CFStringRef ASIHTTPRequestTestsRunMode = CFSTR("ASIHTTPRequestTestsRunMod
[
networkQueue
release
];
}
-
(
void
)
testPartialResume
{
complete
=
NO
;
NSString
*
temporaryPath
=
[[[[
NSBundle
mainBundle
]
bundlePath
]
stringByDeletingLastPathComponent
]
stringByAppendingPathComponent
:
@"MemexTrails_1.0b1.zip.download"
];
if
([[
NSFileManager
defaultManager
]
fileExistsAtPath
:
temporaryPath
])
{
[[
NSFileManager
defaultManager
]
removeItemAtPath
:
temporaryPath
error
:
nil
];
}
NSString
*
downloadPath
=
[[[[
NSBundle
mainBundle
]
bundlePath
]
stringByDeletingLastPathComponent
]
stringByAppendingPathComponent
:
@"MemexTrails_1.0b1.zip"
];
if
([[
NSFileManager
defaultManager
]
fileExistsAtPath
:
downloadPath
])
{
[[
NSFileManager
defaultManager
]
removeItemAtPath
:
downloadPath
error
:
nil
];
}
NSURL
*
downloadURL
=
[
NSURL
URLWithString
:
@"http://trails-network.net/Downloads/MemexTrails_1.0b1.zip"
];
networkQueue
=
[[
ASINetworkQueue
alloc
]
init
];
ASIHTTPRequest
*
request
=
[[[
ASIHTTPRequest
alloc
]
initWithURL
:
downloadURL
]
autorelease
];
[
request
setDownloadDestinationPath
:
downloadPath
];
[
request
setTemporaryFileDownloadPath
:
temporaryPath
];
[
request
setAllowResumeForFileDownloads
:
YES
];
[
networkQueue
addOperation
:
request
];
[
networkQueue
go
];
// Let the download run for 5 seconds, which hopefully won't be enough time to grab this file. If you have a super fast connection, this test may fail, serves you right for being so smug. :)
NSTimer
*
timeoutTimer
=
[
NSTimer
scheduledTimerWithTimeInterval
:
5
target
:
self
selector
:
@selector
(
stopQueue
:
)
userInfo
:
nil
repeats
:
NO
];
while
(
!
complete
)
{
[[
NSRunLoop
currentRunLoop
]
runUntilDate
:[
NSDate
dateWithTimeIntervalSinceNow
:
1
]];
}
// 5 seconds is up, let's tell the queue to stop
[
networkQueue
cancelAllOperations
];
[
networkQueue
release
];
networkQueue
=
[[
ASINetworkQueue
alloc
]
init
];
unsigned
long
long
downloadedSoFar
=
[[[
NSFileManager
defaultManager
]
fileAttributesAtPath
:
temporaryPath
traverseLink
:
NO
]
fileSize
];
BOOL
success
=
(
downloadedSoFar
>
0
);
GHAssertTrue
(
success
,
@"Failed to download part of the file, so we can't proceed with this test"
);
request
=
[[[
ASIHTTPRequest
alloc
]
initWithURL
:
downloadURL
]
autorelease
];
[
request
setDownloadDestinationPath
:
downloadPath
];
[
request
setTemporaryFileDownloadPath
:
temporaryPath
];
[
request
setAllowResumeForFileDownloads
:
YES
];
[
networkQueue
addOperation
:
request
];
[
networkQueue
go
];
[
networkQueue
waitUntilAllOperationsAreFinished
];
unsigned
long
long
amountDownloaded
=
[[[
NSFileManager
defaultManager
]
fileAttributesAtPath
:
downloadPath
traverseLink
:
NO
]
fileSize
];
success
=
(
amountDownloaded
==
9145357
);
GHAssertTrue
(
success
,
@"Failed to complete the download"
);
[
networkQueue
release
];
timeoutTimer
=
nil
;
}
-
(
void
)
stopQueue
:
(
id
)
sender
{
complete
=
YES
;
}
@end
...
...
Please
register
or
login
to post a comment